Dictionary of classes that implement a generic interface - c#

I have a generic interface with two type parameters with severe generic constraints, and several implementations for different combinations.
public interface IResolver<TIn, TOut> where ... {...}
I want to create a (static) resolver factory that will store instances of the known implementations, and just serve them, along the lines:
public static ResolverFactory{
public static IResover<TIn, TOut> GetResolver<TIn, TOut> where ... ()
{
//access some storage dictionary to return the correctly typed instance
}
}
How can I create such a containter, that will store both IResover<Entity1, Entity2> and IResolver<Entity3, Entity4>?
One option I can think of is to use a separate non-generic "marker" interface like:
public interface IResolver {}
public interface IResolver<TIn, TOut> : IResolver where ....
{...}
and use
Dictionary<Type, Dictionary <Type, IResolver>> storage;
public RegisterResolver(IResolver resolver)
{
//add to storage - how?
}
but this scenario basically invalidates the constraints put on the generic parameters.
Also when adding the IResolver, getting the generic types of the IResolver<TIn, TOut> is more or less impossible.
Is there a better solution to this?

There may be something obvious I'm missing in your question, because I don't understand where the issue is.
First, I declare a IResolver<TIn, TOut> interface with a constraint:
public interface IResolver<TIn, TOut>
where TIn : Stream
{
}
Then, I create a ResolverFactory, where the constraints are enforced by both the RegisterResolver and GetResolver method. The way the objects are actually stored doesn't matter, because the storage isn't exposed outside of the class. The encapsulation maintains the consistency:
public static class ResolverFactory
{
private static Dictionary<Type, object> storage = new Dictionary<Type, object>();
public static void RegisterResolver<TIn, TOut>(IResolver<TIn, TOut> resolver) where TIn : Stream
{
storage[typeof(IResolver<TIn, TOut>)] = resolver;
}
public static IResolver<TIn, TOut> GetResolver<TIn, TOut>() where TIn : Stream
{
return storage[typeof(IResolver<TIn, TOut>)] as IResolver<TIn, TOut>;
}
}

Like KooKiz's answer, but no casting, and no dictionary. Usage is similar.
//Rather than:
var res = ResolverFactory.GetResolver<Stream, Hat>();
//You Do:
var res = ResolverFactory<Stream, Hat>.GetResolver();
Just moved the generic parameters, with added advantage of defining generic constraints in fewer places.
public interface IResolver<TIn, TOut>
where TIn : Stream
{
}
//Still static, but now there is one per TIn,TOut pair
//so no need for dictionary, so also no need for casting.
public static class ResolverFactory<TIn, TOut> where TIn : Stream
{
private static IResolver<TIn, TOut> _resolver;
public static void RegisterResolver(IResolver<TIn, TOut> resolver)
{
_resolver = resolver;
}
public static IResolver<TIn, TOut> GetResolver()
{
return _resolver;
}
}
internal class Program
{
private static void Main(string[] args)
{
ResolverFactory<Stream, Hat>.RegisterResolver(new MyStreamToHatResolver());
var res = ResolverFactory<Stream, Hat>.GetResolver();
}
}

Related

When using generics, how do I define a static instantiator of the generic type?

My goal (so that I don't run into an x-y problem):
I am trying to make a Filter class which works with a T generic type. Since the filter works Vector operations, I want to convert the object to a Vector<double>, do the filtering and then convert it back to T once the data is requested.
Interface cannot have static methods
I made an interface that should look something like this.
public interface IFilterable {
public Vector<double> ToVector();
public static IFilterable FromVector(Vector<double> vec);
}
So that I can use it over in the Filter:
public class Filter<T> where T: IFilterable {
private Vector<double> _state;
public T GetState() {
return T.FromVector();
}
Interfaces cannot have static methods, so I'm looking for an alternative that gives me this behavior, that still allows me to use T as the generic type.
Thanks to #Fildor for a solution with interfaces:
public interface IFilterable<out T> where T: new() {
abstract Vector<double> ToVector();
T FromVector(Vector<double> vec);
}
Which can be used by the Filter like this:
public class Filter<T> where T : IFilterable<T>, new() {
private Vector<double> _state;
public T GetState() {
return new T().FromVector(_state);
}
}
Additional solutions include using an abstract class instead of an interface.

C# Playing with generics, reflection and type inference

I'm doing some experiments with generic types and I'm struggling to achieve what I'm looking for. I'm actually not sure that it's even possible to do that. Here's a sample :
public class Request { }
public class RequestTest : Request { }
public class Response { }
public class ResponseTest : Response { }
public abstract class Base
{
// some stuff
}
public abstract class WebMethodBase<TInput, TOutput> : Base
where TInput : Request
where TOutput : Response
{
public abstract TOutput Execute();
protected TInput Input { get; set; }
protected TOutput Output { get; set; }
public WebMethodBase(TInput input, TOutput output)
{
Input = input;
Output = output;
}
}
public class Test : WebMethodBase<RequestTest, ResponseTest>
{
public override ResponseTest Execute()
{
// Do some treatment with the input
Console.WriteLine("Test");
return Output;
}
public Test(RequestTest input, ResponseTest output) : base(input, output) { }
}
public static class WebMethodBaseHelper
{
public static WebMethodBase<TInput, TOutput> Create<TInput, TOutput>(TInput input, TOutput output)
where TInput : Request
where TOutput : Response
{
Type baseType = typeof(WebMethodBase<TInput, TOutput>);
Type childType = baseType.Assembly.GetTypes().Where((t) => baseType.IsAssignableFrom(t) && t.IsClass).FirstOrDefault();
var constructor = childType.GetConstructor(new Type[] { typeof(TInput), typeof(TOutput) });
return (WebMethodBase<TInput, TOutput>)constructor.Invoke(new Object[] {input, output});
}
class Program
{
private static TOutput Execute<TInput, TOutput>(TInput input, TOutput output)
where TInput : Request
where TOutput : Response
{
WebMethodBase<TInput, TOutput> webMethod = WebMethodBaseHelper.Create(input, output);
return webMethod.Execute();
}
private static ResponseTest Run(RequestTest request)
{
return Execute(request, new ResponseTest());
}
static void main(string[] args)
{
ResponseTest result = Run(new RequestTest());
}
}
This sample is working but it's unclear for anyone who would read that code which implementation of WebMethodBase<> is instanciated when you call the Execute method. What I'd like to achieve is to modify the Execute method to be able to call it this way inside the Run method :
return Execute<Test>(request);
Since the Test class is inheriting WebMethodBase<> I guess somehow we should be able to retrieve the generic types and make the whole function generic as well, but I'm not really sure that this is something possible. I tried a lot of different ways already and this is the closest implementation I was able to get from what I want.
Any help to achieve this or explanation of why this is not possible would be much appreciated.
Thanks
Edit
I'm able to get what I want by having the following :
private static TOutput Execute<TMethod, TInput, TOutput>(TInput input)
where TMethod : WebMethodBase<TInput, TOutput>
where TInput : Request
where TOutput : Response, new()
{
TOutput output = new TOutput();
var constructor = typeof(TMethod).GetConstructor(new Type[] { typeof(TInput), typeof(TOutput) });
TMethod instance = (TMethod)constructor.Invoke(new Object[] { input, output });
return instance.Execute();
}
And calling it this way :
return Execute<Test, RequestTest, ResponseTest>(request);
But I don't want to have to specify all three types each time I need to call the Execute method.
I finally found a solution to my issue. I wasn't really aware of the covariance concept and this helped me to achieve what I was looking for.
Below the changes I did to the sample I gave in the original question.
Added a covariant generic interface
public interface IWebMethodBase<out T1, out T2>
where T1 : Request
where T2 : Response
{
T2 Execute();
}
Then modified the WebMethodBase<> class to implement this interface
public abstract class WebMethodBase<TInput, TOutput> : Base, IWebMethodBase<TInput, TOutput>
where TInput : Request
where TOutput : Response
{
public abstract TOutput Execute();
protected TInput Input { get; set; }
public WebMethodBase(TInput input)
{
Input = input;
}
}
Changed as well the Test class which inherits of the one above to reflect its changes and finally the Execute method
public static Response Execute<T>(Request request)
{
ConstructorInfo constructor = typeof(T).GetConstructor(new Type[] { request.GetType() });
T instance = (T)constructor.Invoke(new Object[] { request });
return instance.Execute();
}
And to call it
ResponseTest result = Execute<Test>(new RequestTest()) as ResponseTest;
Using this covariant interface allows the caller to use any generic type that inherits or derives from the applied constraint and make it work as I wanted.
The only thing that I tried to improve there is the needed cast from the final caller, but I didn't find any way to achieve this, apparently it's the compiler itself that refuses to implicitly cast the return value to its derived implementation. I know it's possible in VB.Net using option strict off which I don't recommend, but that's all.
If there's anyone with a better solution or improvements to make to mine, feel free to edit this answer.

Cast generic class to interface

I have a problem with casting a generic class to the interface it is implementing.
My code is like this:
interface foo
{
void foobar();
}
class bar: foo
{
public void foobar()
{
throw new NotImplementedException();
}
}
now I have my factory that creates instances of my classes by the interface, mostly a simple microkernel (service locator). I will simplify it here. Normally it will look up the implementing class from the configs and the factory take the type as T but that doesn't matter for the problem I have.
public static class Factory
{
public static Lazy<foo> CreateLazyInstance()
{
Lazy<foo> instance;
Type type = typeof(bar);
Type lazyType = typeof(Lazy<>);
Type toContruct = lazyType.MakeGenericType(type);
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
return instance;
}
}
If will fail at:
instance = (Lazy<foo>)Activator.CreateInstance(toContruct);
and claim with an InvalidCastException that it is not possible to cast the type Lazy<bar> to Lazy<foo>.
Is there any way to tell the CLR that this cast will work or to workaround this problem?
No - Lazy<T> is invariant - so a Lazy<string> is not a Lazy<object> for example. (As pointed out in comments, it couldn't be declared as covariant in T, as it's a class, not an interface or delegate.)
However, you can convert one to the other easily enough:
static Lazy<TOutput> CreateLazyProxy<TInput, TOutput>
(Lazy<TInput> input) where TInput : TOutput
{
return new Lazy<TOutput>(() => input.Value);
}
Also, Func<T> is covariant, so this will work too:
static Lazy<TOutput> CreateLazy<TInput, TOutput>(Func<TInput> func)
where TInput : TOutput
{
return new Lazy<TOutput>(func);
}
(Not that you particularly need a method for that - if you've got a Func<TInput>, just construct a Lazy<TOutput> directly.)
An easier way to do this would be to pass in a lambda to the Lazy constructor. So, your code would look like the following:
public static Lazy<foo> CreateLazyInstance()
{
Type type = typeof(bar);
return new Lazy<foo>(() => (foo)Activator.CreateInstance(type));
}
You must do your foo generic parameter : new():
public static Lazy<foo> CreateLazyInstance() where foo : new()
And change your code to find a constructor and call it:
Type t = typeof(foo);
t.GetConstructor(new type[]{});
return (foo)t.Invoke(new object[]{});

Question about generics in C# comparing to Java

In Java I can specify generic with wildcard "?". It is possible to create a map like this one:
Map<String, ?>.
I'm working with C# and I need a Dictionary<String, SomeInterface<?>> (where ? can be int, double, any type). Is this possible in C#?
EDIT:
Example:
interface ISomeInterface<out T>{
T Method();
void methodII();
}
class ObjectI : ISomeInterface<int>{
...
}
class ObjectII : ISomeInterface<double>{
...
}
class ObjectIII : ISomeInterface<string>{
....
}
I was trying to map this objects into Dictionary like:
Dictionary<String, ISomeInterface<?>> _objs = new Dictionary<String, ISomeInterface<?>();
_objs.Add("Object1", new ObjectI());
_objs.Add("Object2", new ObjectII());
_objs.Add("Object3", new ObjectII());
foreach(var keyVal in _objs){
Console.WriteLine(keyVal.Method());
}
Objects that implement ISomeInterface are loaded in runtime using Assembly and Activator.createInstance. In the moment of creation I don't if objects implements ISomeInterface<int> or ISomeInterface<double>.
Any help is very much appreciated.
No.
However, if you're using C# 4, you can make ISomeInterface covariant so that ISomeInterface<Anything> will be convertible to ISomeInterface<object>.
If ISomeInterface has methods that take parameters of its type parameter (as opposed to return values), this will be completely impossible, since it would then allow you to pass arbitrary objects as the parameters.
EDIT: In your specific case, the best solution is to make IMyInterface<T> inherit a separate non-generic IMyInterface interface and move all members that don't involve T to the base interface.
You can then use a Dictionary<string, IMyInterface> and you won't have any trouble.
There is the possibility to restrict your type variables to certain types:
public class Map<U, T> where T : IInterface
{
}
However, you can't do something like:
Map<string, T> map = new Map<string, T>()
For the usage you're describing, you could use a workaround, with an IDictionary<string, ISomeInterface>:
interface ISomeInterface
{
object Method();
void Method2();
}
interface ISomeInterface<T> : ISomeInterface
{
T Method();
}
class C1 : ISomeInterface<int>
{
object ISomeInterface.Method() { return Method(); }
public int Method() { return 10; }
public void Method2() { }
}

Is it possible to reuse a generic type to call a method with additional constraints?

Example 1
Assume a method that decides which method should be used to convert a value.
public static TTarget ConvertValue<TTarget>(object value)
{
Type t = typeof(TTarget);
if (t.IsEnum)
return ParseEnum<TTarget>(value);
else //if ...
return ...;
}
Some methods that handle the value have a generic type parameter with constraints.
public static TEnum ParseEnum<TEnum>(object value)
where TEnum : struct
{
//do something
return ...;
}
The compiler doesn't allow this approach because the type TTarget isn't necessarily a struct and can become NULL and thus cannot be used as TEnum.
Example 2
Assume having a generic method without constraints and a method with additional constraints:
public void DoStuff<T>(T obj)
{
if (obj is IComparable && obj is ICloneable)
DoSpecialStuff<T>(obj);
}
public void DoSpecialStuff<T>(T obj)
where T : IComparable, ICloneable
{
}
This also doesn't work because there is (afaik) no way to cast to multiple interfaces.
Is it possible to reuse a generic type to call a method with additional constraints?
You need to invoke the method using Reflection.
There is no better way.
You should consider calling a non-generic method instead (and passing typeof(TTarget) as a parameter)—ParseEnum shouldn't need to be generic.
As SLaks mentions, the only way to achieve this is by using reflection. Here's one way of doing it. (The delegates are cached in a dictionary so that subsequent calls for the same type don't need reflection.)
public static TTarget ConvertValue<TTarget>(this object value)
{
Type t = typeof(TTarget);
if (t.IsEnum)
{
Delegate del = _delegateCache.GetOrAdd(t, t2 =>
Delegate.CreateDelegate(typeof(Func<object, TTarget>),
_parseEnumInfo.MakeGenericMethod(t2));
return ((Func<object, TTarget>)del)(value);
}
else // if ...
return ...;
}
private static readonly MethodInfo _parseEnumInfo =
typeof(YourParentClass).GetMethod("ParseEnum");
private static readonly ConcurrentDictionary<Type, Delegate> _delegateCache =
new ConcurrentDictionary<Type, Delegate>();
public static TEnum ParseEnum<TEnum>(object value)
where TEnum : struct, IComparable, IConvertible, IFormattable
{
// do something
return ...;
}
Or, to match your second example:
public void DoStuff<T>(T obj)
{
if ((obj is IComparable) && (obj is ICloneable))
{
Delegate del = _delegateCache.GetOrAdd(typeof(T), t =>
Delegate.CreateDelegate(typeof(Action<T>),
this,
_doSpecialStuffInfo.MakeGenericMethod(t));
((Action<T>)del)(obj);
}
}
private static readonly MethodInfo _doSpecialStuffInfo =
typeof(YourParentClass).GetMethod("DoSpecialStuff");
private readonly ConcurrentDictionary<Type, Delegate> _delegateCache =
new ConcurrentDictionary<Type, Delegate>();
public void DoSpecialStuff<T>(T obj)
where T : IComparable, ICloneable
{
}
If for each interface of interest you define a version with an "extra" generic parameter T which inherits both the generic interface and ISelf<out T> (I'd suggest that interface contain a single read-only property "self", of type T), and if each class of interest implements ISelf<ItsOwnType>, then if e.g. IFoo<T> inherits from IFoo and T, a routine that needs something to implement both IFoo and IBar could accept a parameter of type IFoo<IBar>. If the passed-in parameter is called X, X will implement IFoo and X.Self will implement IBar. The beautiful thing about this approach is that any such object implementing any combination of interfaces defined in this way can be typecast to something which will implement any combination of those interfaces, in any order. The one weakness with this approach is that it presumes that objects will define ISelf<T>.Self to return themselves, but there's no real guarantee that such an object won't return something else instead.

Categories

Resources