Go to a generic interface with a dynamic type parameter

I have two common interfaces:

public interface IFoo<T> { }
public interface IBar<TFoo, T> where TFoo : Foo<T> { 
    T Qux(TFoo foo);
}

      

IFoo<T>

has a variety of implementations, each with a corresponding implementation IBar<S,T>

registered in my IoC container (which happens to be Castle.Windsor).

Now I want to create a method that, based on an argument of some type that implements IFoo<T>

, returns the corresponding one IBar<IFoo<T>,T>

from Windsor. A naive implementation looks like this:

public IBar<TFoo,T> GetBarFor(IFoo<T> foo) where TFoo : IFoo<T>
{
    return container.Resolve<IBar<TFoo,T>>();
}

      

However, in the calling code, I don't have it specifically printed Foo<T>

- just IFoo<T>

:

public T DoStuffWithStuff<T>(IFoo<T> foo)
{
    var bar = GetBarFor(foo);
    return bar.Qux(foo);
}

      

and in this call the compiler cannot infer the type parameters (in particular, I think TFoo

), so I need to take a different approach.

I tried to resolve the non-generic type Resolve()

, but then I can't get the correct return type:

public AbstractBar<T> GetBarFor(IFoo<T> foo) where TFoo : IFoo<T>
{
    var barType = typeof(IBar<,>).MakeGenericType(foo.GetType(),typeof(T));
    var bar = container.Resolve(barType); // bar is now a System.Object

    var wrapperType = typeof(BarWrapper<,>).MakeGenericType(foo.GetType(), typeof(T));
    var wrapper = Activator.CreateInstance(wrapperType, bar);

    return (AbstractBar<T>)wrapper;
}

      

from

public abstract class AbstractBar<T> { public abstract T Qux(IFoo<T> foo); }

public class BarWrapper<TFoo, T> : AbstractBar<T> where TFoo : IFoo<T>
{
    private IBar<TFoo,T> _inner;
    public BarWrapper(IBar<TFoo,T> inner) { _inner = inner; }

    public T Qux(IFoo<T> foo) { return _inner.Qux((TFoo)foo); }
}

      

but I keep getting exceptions from the call Activator.CreateInstance

saying the constructor for BarWrapper

not found (yes, everything is public

).

Is there a good way to get the call in DoStuffWithStuff

above that works exactly for this signature (i.e. I cannot defer any more specific generics from the calling code)?


Footnote: I've seen the latter pattern work, Jimmie Bogard MediatR's implementation of the mediator pattern , and in fact what I'm trying to do here is a very similar implementation that doesn't rely on the Common Service Locator, but rather directly on our IoC container. In context IFoo<T>

really IRequest<out TResponse>

, IBar<TFoo, T>

really IRequestHandler<in TRequest, out TResponse>

, etc.

Looking at his code and trying to recreate it, but with a call to the Windsor container instead of the service locator, I can't figure out why his code works and mine doesn't.

+3


source to share


2 answers


Untested, but you need to use reflection to later associate the type with information about the generic type method you want to execute.



      var wrapperType = typeof(BarWrapper<,>).MakeGenericType(foo.GetType(), typeof(T));

      MethodInfo TempMethodInfo = typeof(MYClass).GetMethod("DoStuffWithStuff")         

      MethodInfo GenericParam = TempMethodinfo.MakeGenericMethod(T);

      var Formatter = Delegate.CreateDelegate(wrapperType , GenericParam);

      

0


source


You can use the old keyword dynamic

.

Essentially, this allows runtime to determine the correct types.

IBar<TFoo,T> GetBarFor<TFoo, T>(TFoo dummy, IFoo<T> secondDummy) 
    where TFoo : IFoo<T>
{
    return container.Resolve<IBar<TFoo, T>>();
}

      



and use GetBarFor

:

GetBarFor((dynamic)foo, (dynamic)foo);

      

0


source







All Articles