Autofac - Resolve Generics by base class - c#

I have a mapping hierarchy of interfaces/classes that use generics constrained by a base class and I am trying to resolve them to their derived classes using the base classes. I am wondering if Autofac can resolve this in a better way than I am currently doing it.
Taking the following structure:
public interface IMapper<T1, T2>
where T1 : FooBase
where T2 : BarBase
{
T1 Map(T2 source);
}
public class FooBarMapper : IMapper<Foo, Bar>
{
public Foo Map(Bar source)
{
return new Foo
{
blahblah = source.xyz
};
}
}
Next, I have a "To" extension method on "Foo" which references the base types, but I want to resolve it to a proper type. I currently resolve like this:
public static TDest To<TDest>(this BarBase o) where TDest : FooBase
{
var genericMapper = typeof(IMapper<,>).MakeGenericType(o.GetType(), typeof(TDest));
object mapper = IocProxy.Container.Resolve(genericMapper);
//... etc
}
This resolves fine... but mapper is just an object. So I'd have to use reflection to hit the "Map" method. Which I'd rather avoid doing. Can autofac do this in a better way so that I end up with an IMapper as opposed to an object? For example, I'd prefer to do something like this, but autofac obviously doesn't resolve it:
var mapper = IocProxy.Container.Resolve<IMapper<FooBase, TDest>>();

The answer to this problem is a bit ugly. Because you can't create the "To" extension method with 1 generic, you have to make the code look ugly so that it can infer both types. Like this:
public static TDest To<TDest,TSource>(this TSource o) where TDest : new()
{
var mapper = IocProxy.Container.Resolve<IMapper<TSource, TDest>>();
return mapper.Map(o);
}
Somewhere deeper down we get this ugly call:
var b = a.To<Bar,Foo>(); //<-- to convert it to "Bar" we need to specify both generics
Yes, ugly! Who really knows what's getting mapped to what here! Unless you explicitly specify the type, but you know how var crazy some people have gone these days.
Anyway, as I don't like this I developed a workaround to improve readability. Firstly, I created a Map class to wrap my object (and my "To" function). This is an extra step, but acts as a nice intermediary for helping autofac resolve the generics correctly:
public class Map<TSource> where TSource : new()
{
public TSource Object { get; set; }
public Map(TSource o)
{
Object = o;
}
public TDest To<TDest>()
{
var mapper = IocProxy.Container.Resolve<IMapper<TSource, TDest>>();
return mapper.Map(Object);
}
}
And then a slightly different generic extension method to get the Mapper back (and get the code into the style I wanted):
public static Map<TDest> Map<TDest>(this TDest o) where TDest : new()
{
return new Map<TDest>(o);
}
This does slightly change how I wanted to call it, but it reads equally as well.
So rather than this:
foo.To<Bar, Foo>();
The code looks like this
foo.Map().To<Bar>()
You could even extend it further and add and interface to the Map class and get Autofac to resolve it, but I guess it depends on how often you are spinning up mappers. And in the end the performance gain is probably negligible.

Related

Apply generic visitor to generic derived class of non-generic base class

Currently I have something like this:
public abstract class Base {...}
public class Derived<T> : Base {...}
class Visitor {
public static void Visit<T>(Derived<T> d) {
...
}
}
My question is, given a Base reference that I know is a Derived instance, how can I apply that Visit function to that object, using the correct generic instantiation? I understand that the answer will probably involve a type-checked dynamic downcast, to make sure that the object isn't some other type derived from base, which is all fine. I assume the answer involves reflection, which is also fine, though I'd prefer if there was a way to do it without reflection.
It's also ok if the answer involves an abstract method on Base and Derived; I do have enough control of the classes to add that. But at the end of the day, I need to call a generic function, correctly instantiated with the T of the Derived type.
Sorry if this is an easy question; I come from a C++ background, where my instinct would be to use a CRTP or something else like that, which isn't possible in C#.
EDIT:
Here's an example of what I need to be able to do:
Base GetSomeDerivedInstance() { ...; return new Derived<...>(); }
var b = GetSomeDerivedInstance();
// This is the line that needs to work, though it doesn't necessarily
// need to have this exact call signature. The only requirement is that
// the instantiated generic is invoked correctly.
Visitor.Visit(b);
In my opinion, answers involving double-dispatch and More Classes are going to be superior than using reflection to do what inheritance should do for you.
Normally this means defining an 'accept' method on the visitable class, which simply calls the correct Visit method from the visitor.
class Base
{
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this); // This calls the Base overload.
}
}
class Derived<T> : Base
{
public override void Accept(Visitor visitor)
{
visitor.Visit(this); // this calls the Derived<T> overload.
}
}
public class Visitor
{
public void Visit(Base #base)
{
...
}
public void Visit<T>(Derived<T> derived)
{
...
}
}
Then you can do what you mentioned in your question, with a small modification:
Base b = createDerived();
b.Accept(new Visitor());
If your visit method is a static class that you can't change for whatever reason, you could always wrap this into a dummy instance visitor class which calls the right static method.
(Edited for clarity)
The following will use a variable called "anyvalue" whose type is only known at run-time. Then we'll create an instance of your Derived class based on the type of anyvalue. Once we have that instance, we can use reflection to get the correct Visit method.
var anyvalue = 5; // This value could have come from anywhere.
...
var derivedType = typeof (Derived<>).MakeGenericType(anyvalue.GetType());
var dvalue = Activator.CreateInstance(derivedType);
var method = typeof(Visitor).GetMethod("Visit");
var genericMethod = method.MakeGenericMethod(new[] { anyvalue.GetType() });
genericMethod.Invoke(null, new [] { dvalue });
What is a little confusing is that this is a skeletal example and you do not use the original value for anything other than getting a run-time type. In the real world implementation, I would assume a constructor would use that value to set internal state in the Derived instance. That is not covered here because that is not part of the question that was asked.
UPDATE:
I think this will do what you want. Note that I created the itemarray so that we would have some run-time values. They have to be created somewhere. So whether they are passed in as object[] or provided some other way, they had to be constructed with a type specifier somewhere. Also, this assumes that Derived<> is the only derived class. Otherwise, this is not safe code.
var itemarray = new Base[] { new Derived<int>(), new Derived<string>() };
foreach (var baseObject in itemarray)
{
var derivedType = baseObject.GetType();
var visitMethod = typeof(Visitor)
.GetMethod("Visit")
.MakeGenericMethod(derivedType.GetGenericArguments());
visitMethod.Invoke(null, new[] { baseObject });
}
The Accept approach does seem a bit more manageable. My goal was to answer the question you asked without passing judgment on your approach. I have needed to use this approach several times. I wrote an entity framework about 9 years ago. I had a really hard time doing exactly what you are trying to do. I created base classes that were not generic so that I could share basic functionality regardless of the generic type. It proved challenging. I am not sure I would do it the same way now. I'd probably investigate a few patterns just as you are doing.
You should be able to do something like the following:
Base foo = new Derived<int>();
var method = typeof(Visitor).GetMethod("Visit", BindingFlags.Public | BindingFlags.Static);
method.MakeGenericMethod(foo.GetType().GenericTypeArguments.First()).Invoke(null, new[] {foo});
Perhaps you're meaning something like this?
public class Derived<T>
{
}
public abstract class Derivable<T>
{
public Derived<T> CreateDerived()
{
return new Derived<T>();
}
}
public class Foo : Derivable<Foo>
{
}
class Visitor
{
public static void Visit<T>(Derived<T> obj)
{
Console.Out.WriteLine("Called!");
}
}
void Main()
{
var obj = new Foo();
var derived = obj.CreateDerived();
Visitor.Visit(derived);
}
If the creation of the Derived<T> is T-specific, then you'd make the CreateDerived method abstract and implement it for each T. Or use an IDerivable<T> interface instead if you don't want it as your base class.

How do I write an interface or abstract class that specifies creation logic?

I have a generic class that deals with widgets that can be deserialized from strings. Instances of the generic class will take the type of one of these widgets as a template parameter, and then create these widgets from strings. I wish to use the covariance properties of C#'s generics to write code like WidgetUser<IWidget> to deal with objects that may be WidgetUser<RedWidget> or WidgetUser<BlueWidget>. The problem is that to create a widget from a string inside of WidgetUser<T>, I'm forced to add new() as a guard. This makes WidgetUser<IWidget> an invalid type. Currently, I have code like this:
interface IWidget
{
// Makes this widget into a copy of the serializedWidget
void Deserialize(string serializedWidget);
}
class WidgetUser<T> where T : IWidget, new()
{
public void MakeAndUse(string serializedWidget)
{
var widget = new T();
widget.Deserialize(serializedWidget);
Use(widget);
}
}
With this code, I can make WidgetUser<BlueWidget> just fine, because BigWidget satisfies new(). I cannot write WidgetUser<IWidget> because instances of IWidget (or an equivalent abstract class) are not guaranteed to work with new(). A workaround could be this:
abstract class WidgetUser
{
public abstract void MakeAndUse();
}
class WidgetUser<T> : WidgetUser
where T : IWidget, new()
{
/* same as before but with an 'override' on MakeAndUse */
}
With this code, I can create a WidgetUser<BlueWidget> then write code that deals with just WidgetUser. I could have similar code with an abstract class BaseWidget instead of IWidget that accomplishes almost the same thing. This is functional, but I suspect there is a more direct approach that doesn't force me to define a dummy class. How can I convey my intent to the type system without creating dummy classes or extra factories. I just want an interface that says "you can make one of these from a string".
TL;DR:
Is there some way to write an interface or abstract class that lets me create an instance from a string but doesn't require me to have new() as a guard on WidgetUser<T>?
The problem here is that your Deserialize() method should be a static method. Therefore it should not be a member of IWidget itself - it should be a member of a factory interface, or it should be a static member of a concrete Widget class which is called from a concrete factory method. I show the latter approach below.
(Alternatively, you could use a Func<IWidget> delegate to specify it, but it's more usual to provide a full factory interface.)
So I suggest you create the factory interface:
interface IWidgetFactory
{
IWidget Create(string serialisedWidget);
}
Then remove the Deserialize() from IWidget:
interface IWidget
{
// .. Whatever
}
Then add a static Deserialize() method to each concrete implementation of IWidget:
class MyWidget: IWidget
{
public static MyWidget Deserialize(string serializedWidget)
{
// .. Whatever you need to deserialise into myDeserializedObject
return myDeserializedObject;
}
// ... Any needed IWidget-implementing methods and properties.
}
Then implement the factory for your concrete widget class using the static Deserialize() method from the concrete widget class:
sealed class MyWidgetFactory : IWidgetFactory
{
public IWidget Create(string serialisedWidget)
{
return MyWidget.Deserialize(serialisedWidget);
}
}
Then add a constructor to your WidgetUser class which accepts an IWidgetFactory and use it in MakeAndUse():
class WidgetUser
{
public WidgetUser(IWidgetFactory widgetFactory)
{
this.widgetFactory = widgetFactory;
}
public void MakeAndUse(string serializedWidget)
{
var widget = widgetFactory.Create(serializedWidget);
Use(widget);
}
private readonly IWidgetFactory widgetFactory;
}
Note that in this scenario, you no longer need the type argument for WidgetUser, so I have removed it.
Then when you create the WidgetUser you must supply a factory:
var widgetUser = new WidgetUser(new MyWidgetFactory());
...
widgetUser.MakeAndUse("MySerializedWidget1");
widgetUser.MakeAndUse("MySerializedWidget2");
Passing in a factory allows a lot more flexibility.
For example, imagine that your serialization scheme included a way of telling from the serialized string which kind of widget it is. For the purposes of simplicity, assume that it starts with "[MyWidget]" if it's a MyWidget and starts with ["MyOtherWidget"] if it's a MyOtherWidget.
Then you could implement a factory that works as a "virtual constructor" that can create any kind of Widget given a serialization string as follows:
sealed class GeneralWidgetFactory: IWidgetFactory
{
public IWidget Create(string serialisedWidget)
{
if (serialisedWidget.StartsWith("[MyWidget]"))
return myWidgetFactory.Create(serialisedWidget);
else if (serialisedWidget.StartsWith("[MyOtherWidget]"))
return myOtherWidgetFactory.Create(serialisedWidget);
else
throw new InvalidOperationException("Don't know how to deserialize a widget from: " + serialisedWidget);
}
readonly MyWidgetFactory myWidgetFactory = new MyWidgetFactory();
readonly MyOtherWidgetFactory myOtherWidgetFactory = new MyOtherWidgetFactory();
}
Note that this is generally not the best way to do things - you are better using a Dependency Container such as Autofac to manage this kind of thing.
I would implement WidgetFactory and call WidgetFactory.Create<T>(serializedWidget) to avoid the usage of new T()

C# Generics and abstract factory pattern - or some way of doing something similar

I am trying to write a sort of extendable data layer for my application One of the "repositories" is an in-memory implementation of my abstract store class
public abstract class Store<TEntity, TIdentifier> : IStore<TEntity, TIdentifier>
where TEntity : StorableEntity<TIdentifier>
{
//abstract methods here
public abstract TIdentifier GetUniqueIdentifier();
}
The "StorableEntity" abstract class is:
public abstract class StorableEntity<TIdentifier>
{
public TIdentifier ID { get; set; }
}
I have a concrete class of Store called "InMemoryStore" that looks like this:
public class InMemoryStore<T, U> : Store<T, U>
where T : StorableEntity<U>
{
protected static Dictionary<U, T> store = new Dictionary<U, T>();
public override U GetUniqueIdentifier()
{
// call relevant "generator" here - SOMETHING LIKE THIS??
// var generator = GetGeneratorSomehow(U);
// return generator.Create();
}
}
Now, the type of "U" here could be string, int, Guid etc...
(most of the time it could be int)
My idea here is to create something like an IUIDGenerator like this:
public interface IUIDGenerator<T>
{
T Create(ICollection<T> collection);
}
In the above "InMemoryStore" i would then create an instance of an IUIDGenerator, pass in the store dictionarys key collection, and call the "Create" method to return a unique identifier of the required type.
For example, i could have an IntUIDGenerator class like this (that would act as a kind of incremental number generator, based on the numbers already in the dictionary keys)
public class IntUIDGenerator : IUIDGenerator<int>
{
public int Create(ICollection<int> collection)
{
var result = collection.Max() + 1;
if (collection.Contains(result))
return result;
throw new NotUniqueException();
}
}
Actual Question:
What I need to do, is within InMemoryStore, identify the type of U (the type of the identifier) and be able to dynamically select the required concrete implementation of IUIDGenerator - how can i do this?
I thought about having a type of class factory pattern - loading all the available UIDGenerators into a dictionary... but they can all have different types?
Is there a better way around this?
Also, I am aware the title of my question may be a bit off - if anyone has a better suggestion, please feel free to comment and I'll change it.
You could use an IoC framework, such as Unity, Castle, Ninject, etc. Then you'd configure your container with something like the following:
_container = new UnityContainer();
_container.RegisterType<IUIDGenerator<int>, IntUIDGenerator);
_container.RegisterType<IUIDGenerator<Guid>, GuidUIDGenerator);
Then in your class you've have something like the following:
public override U GetUniqueIdentifier()
{
var generator = _container.Resolve<IUIDGenerator<U>>();
return generator.Create();
}
I think you'll have to use at least one cast. If you store all your generators in a map like
Map<Type, object> generators;
you can use
class InMemoryStore<T,U> {
public override U GetUniqueIdentifier() {
var generator = generators[typeof(U)] as IUIDGenerator<U>;
return generator.Create(collection);
}
}
Of course, I omitted all sort of validation code :) (like checking, if a generator for type U is in the map etc...)
The short answer: Use dependency injection, and let your DI container handle it for you.
You could add an additional generic type argument for the generator, eg
public class InMemoryStore<T, U, V> : Store<T, U>
where T : StorableEntity<U>
where V : IUIDGenerator<U>, new() {
public override U GetUniqueIdentifier()
{
return (V)(Activator.CreateInstance<V>()).Create();
}
}

C# generics based object to object mapper question

I have the need for an object to object mapper in my application. I've tried out a few, but haven't been able to find anything that fits my needs, so I'm writing my own. Currently I have an interface like below:
public interface IMapper<T, R> {
T Map(R obj);
}
I then implement an AccountMapper that maps a Customer to an Account as:
public class AccountMapper : IMapper<Account, Customer> {
Account Map(Customer obj) {
// mapping code
}
}
This works fine so far, however I have several source entities that map to the same destination entity. For instance I have a Payment and an Invoice that both map to BillHistory. For the above to support this, I need to make two separate mappers (ie. BillHistoryPaymentMapper and BillHistoryInvoiceMapper), which is fine. However, I'd love to be able to implement it slightly differently like below. Only problem is I don't know if it's possible and if so, I don't know the correct syntax.
public interface IMapper<T> {
T Map<R>(R obj);
}
public class BillHistoryMapper : IMapper<Account> {
public BillHistory Map<Invoice>(Invoice obj) {
// mapping code
}
public BillHistory Map<Payment>(Payment obj) {
// mapping code
}
}
While the first implementation works fine, the second would be slightly more elegant. Is this possible and if so what would the correct syntax look like?
edit-------
I hate when people do this, but of course I forgot to mention one little detail. We have an abstract class between the mapper and the interface to implement some common logic across all of the mappers. So my mapper signature is actually:
public class BillHistoryMapper : Mapper<BillHistory, Invoice> {
}
where Mapper contains:
public abstract class Mapper<T, R> : IMapper<T, R> {
public IList<T> Map(IList<R> objList) {
return objList.ToList<R>().ConvertAll<T>(new Converter<T, R>(Map));
}
}
You'll have to use your first interface and implement the interface multiple times on your object:
public class BillHistoryMapper : IMapper<Account, Invoice>,
IMapper<Account, Payment> {
...
}
I would serious consider taking a look at AutoMapper instead of writing your own. There are a lot of nuances in mapping that it has already solved, not to mention it has been through plenty of performance testing, bug fixes, etc.
With regard to your abstract class consider getting rid of it and replacing it with an extension method. This will allow you to use the MapAll function regardless of whether you implement the interface or use some sort of inheritance chain.
public static class MapperExtensions
{
public static IEnumerable<TOutput> MapAll<TInput, TOutput>
(this IMapper<TInput, TOutput> mapper, IEnumerable<TInput> input)
{
return input.Select(x => mapper.Map(x));
}
}
This will now make it easier when trying to solve your problem above because you no longer have to inherit from a base class you can now implement the mapping interface for the types you want to map.
public class BillHistoryMapper :
IMapper<Invoice, BillHistory>, IMapper<Payment, BillHistory>
{
public BillHistory Map<Invoice>(Invoice obj) {}
public BillHistory Map<Payment>(Payment obj) {}
}
Also consider changing your IMapper generic parameters to be the other way round (I took the liberty in the previous examples):
public interface IMapper<in TInput, out TOutput>
{
TOutput Map(TInput input);
}
The reason for this is that it directly maps to the System.Converter<T> delegate and you can do something like:
IMapper<ObjectA, ObjectB> myAToBMapper = new MyAToBMapper();
ObjectA[] aArray = { new ObjectA(), new ObjectA() };
ObjectB[] bArray = Array.ConvertAll<ObjectA, ObjectB>(aArray, myAToBMapper.Map);
List<ObjectA> aList = new List<ObjectA> { new ObjectA(), new ObjectA() };
List<ObjectB> bList = aList.ConvertAll<ObjectB>(myAToBMapper.Map);
// Or
var aToBConverter = new Converter<ObjectA, ObjectB>(myAToBMapper.Map);
bArray = Array.ConvertAll(aArray, aToBConverter);
bList = aList.ConvertAll(aToBConverter);
AutoMapper has also been suggested which will make your life easier. However if you wanted to keep your mapping abstraction and have your code agnostic to your mapping strategy then it is very easy to use the above interface to inject a wrapper around AutoMapper. It will also mean you can continue to use the MapAll extension method explained above.
public class AutoMapperWrapper<in TInput, out TOutput> : IMapper<TInput, TOutput>
{
public TOutput Map(TInput input)
{
return Mapper.Map<TOutput>(input);
}
}
Final word
Also keep in mind you are not always going to find that your mapping strategy will work across the board so don't try to fight your domain and force it to fit your mapping strategy. One particular example is you might have to map from two input items into one. You can obviously make this fit your strategy but you may find it becomes messy. In this particular example consider it a merge.
Your second example will work with only a few changes:
// you have to include the R type in the declaration of the Mapper interface
public interface IMapper<T, R> {
T Map<R>(R obj);
}
// You have to specify both IMapper implementations in the declaration
public class BillHistoryMapper : IMapper<Account, Invoice>, IMapper<Account, Payment> {
public BillHistory Map<Invoice>(Invoice obj) {
// mapping code
}
public BillHistory Map<Payment>(Payment obj) {
// mapping code
}
}
I'm not sure if this actually gains you anything over the existing pattern, though.
If there is a limited number of types you want to map from, then I would use the first method of declaring the input and output types in the interface definition. Then a mapper can implement interfaces for each input type it supports, so your BillHistoryMapper would be declared as:
public class BillHistoryMapper : IMapper<BillHistory, Invoice>, IMapper<BillHistory, Payment>
{
...
}

Problems with abstract types and interafaces as generic type params with the new() constraint

I need to have the generic type parameter as an interface, however I would like to instantiate the type in the generic class (SomeGenericType) as follows:
class Program
{
static void Main(string[] args)
{
var val = new SomeGenericType<ISomeInterface>();
Console.ReadKey();
}
}
internal class SomeGenericType<T> where T : new()
{
public SomeGenericType()
{
var test = new T();
}
}
public class SomeClass : ISomeInterface
{
public string TestVal { get; set; }
}
public interface ISomeInterface
{
string TestVal { get; set; }
}
This throws the following compile time error:
"ISomeInterface must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method SomeGenericType"
I understand why it happens, however I was wondering if there is any way around this problem?
Thanks.
No, the new() constraint requires that an instance of the type can be created with the syntax
new T()
This clearly isn't true of either an abstract class or an interface, only a concrete class with a public parameterless constructor.
You could defer the problem until runtime by removing the constraint, and using:
Activator.CreateInstance<T>()
instead to create the object. Then as long as the actual type used at runtime satisfies these constraints, your code will work as you want it to. However, if you do attempt to use an interface or an abstract class, then you will encounter a runtime error.
In your specific case, this line would throw an exception
var val = Activator.CreateInstance<SomeGenericType<ISomeInterface>>();
You're past the compile-time error, but to no effect.
An alternative idea, which may be irrelevant, but it looks like you are looking for a way to ask for an ISomeInterface, and have an instance of its "default" implementation SomeClass provided. This is the sort of thing that an Inversion of Control (IOC) container can handle for you. If you want to investigate further, you could look at Spring.NET, Microsoft Unity, AutoFac, LinFu or one of many other frameworks.
The problem is, there is no way for the compiler to know which class to instantiate for the given interface. As David M points out:
This is the sort of thing that an Inversion of Control (IOC) container can handle for you
I think using a framework might be over kill for this simple requirement. What you can do is create a Factory class of your own like this:
public class Factory
{
Dictionary<Type, Type> typeMapping = new Dictionary<Type, Type>();
public void Register<IType, CType>()
{
typeMapping.Add(typeof(IType),typeof(CType));
}
public IType Create<IType>()
{
Activator.CreateInstance(typeMapping[typeof(IType)]);
}
}
throw in a few sanity checks and this class should be ready to use.
The issue here is the new constraint is tied to having a concrete type implementation. This can't ever work with simply and interface or abstract class since they cannot be directly instantiated. You must provide a concrete class here
var val = new SomeGenericType<SomeClass>()

Categories

Resources