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>
{
...
}
Related
I want to use C# 8 default interface implementation to face a performance issue in my code.
Actually, I have this intefaces :
public interface IDataAdapter {}
public interface IDataAdapter<T> : IDataAdapter
{
void Insert(T value);
}
I actually have to do reflection across all IDataAdapter, check generic type and call Insert by reflection for a specific T instance. What I wish to do is :
public interface IDataAdapter
{
void InsertValue(object value);
}
public interface IDataAdapter<T> : IDataAdapter
{
void Insert(T value);
public void InsertValue(object value) => Insert(value as T);
}
The compiler says to use the keyword new to mask the inherited method. However, the only thing I'm trying to accomplish is to have a non-generic method already implemented to make all IDataAdapter<T> implementations to only have to implement the generic version.
Is this something I can accomplish or it's still impossible ? I already know that using an abstract class is a way to solve this issue, but I want to allow a developper to have a class that implements many IDataAdapter...
This is my current reflection code :
public IEnumerable<IDataAdapter> DataAdapters { get; }
public Repository(IEnumerable<IDataAdapter> dataAdapters)
{
DataAdapters = dataAdapters;
}
public async Task SaveAsync()
{
foreach (var item in aggregates)
{
foreach (var dataAdapter in DataAdapters)
{
if (dataAdapter.GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericArguments()[0] == item.GetType()))
{
dataAdapter.GetType().GetMethod("Insert", new[] { item.GetType() }).Invoke(dataAdapter, new[] { item });
}
}
}
}
From an object oriented point of view, what you are trying to do can't be done.
Suppose you create the following class hierarchy:
public interface IFoo{}
public interface IBar{}
public class A: IFoo{}
public class B: IFoo{}
public class C:IFoo,IBar {}
And then the following adapters:
public class TestA : IDataAdapter<A>{}
public class TestB : IDataAdapter<B>{}
public class TestC : IDataAdapter<C>{}
public class TestIFoo : IDataAdapter<IFoo>{}
public class TestIBar : IDataAdapter<IBar>{}
public class TestIBoth : IDataAdapter<IFoo>,IDataAdapter<IBar>{}
What should happen if TestA receive an instance of A is quite easy. But what about TestIFoo receive a C? Currently your reflection code won't work because you test type equality (does C equals IFoo? No! Even if C as IFoo is ok).
This breaks Liskov substitution principle. If something works with a class then it should also work with any of its subclasses.
Let's suppose you fix above point. Now what about TestIBoth receiving a C? Is there two different implementation of Insert in it? Of course, this is required by inheritence! But then... do you have to insert C twice? Or do you have to insert it just once in the first fitting method?
The reason why you have to go through reflection is because all those questions needs an algorithmic answer. Your compiler won't be able to answer (which makes the language prevent it by the way)
In the end I would strongly recommend to use a very different solution (like the one proposed by Wim Coenen)
I recognize this problem where you need to look up the IDataAdapter implementation which knows how to handle a certain type of item. I've done something similar for a "view plugin" system, where I would look for the view plugin that knows how to render a certain type. This is useful if you can't know in advance what type of objects you'll need to render.
As far as I know, trying to shoehorn more compile-time type safety into this pattern won't really work, or if it does then it won't actually provide any benefits. I would just declare IDataAdapter like this:
public interface IDataAdapter
{
void InsertValue(object value);
Type SupportedType { get; }
}
If a data adapter supports multiple types, you can make it IEnumerable<Type> SupportedTypes instead, or maybe replace the property by a bool SupportsType(Type) method.
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()
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.
Well, I've had to rewrite this as I've been down voted five times for giving too much detail... Go figure!
class BaseModel
{
public T[] Get<T>()
{
// return array of T's
}
public T Find<T>(object param)
{
// return T based on param
}
public T New<T>()
{
// return a new instance of T
}
}
class BaseRow
{
private BaseModel _model;
public BaseRow(SqlDataReader rdr, BaseModel model)
{
// populate properties of inheriting type using rdr column values
}
public void Save()
{
// calls _model.Save(this);
}
}
I currently have a number of classes that inherit the BaseModel class. Each of the methods exposed by BaseModel will return an instance, or an array of instances of a type that inherits the BaseRow class.
At the moment, when calling the exposed methods on the BaseModel via an inheriting class, i.e.
using(DeviceModel model = new DeviceModel())
{
DeviceRow row = model.Find<DeviceRow>(1);
DeviceRow[] rows = model.Get<DeviceRow>();
DeviceRow newRow = model.New<DeviceRow>();
}
I have to specify the type (a class that inherits the BaseRow class), as the methods in BaseModel/BaseRow do not know/care what type they are, other than they inherit from BaseRow.
What I would like to do is find a way to remove the need to specify the without having to replicate code in every class that inherits BaseModel, i.e.
class DeviceModel : BaseModel
{
public DeviceRow Find(object param)
{
return this.Find<DeviceRow>(param);
}
}
Note: Unfortunately I am unable to implement or use any third party solutions. That said, I have tried using Castle Active Record/nHibernate and to be honest, they are very big and heavy for what should be a very simple system.
Hopefully I haven't provided "too much" detail. If I have, please let me know.
Thanks
If I were you, I'd suggest making BaseModel a generic class. In a situation of "can't win either way", the code you've removed to make others happy might have told me more about what you're doing (not a criticism by any stretch - I appreciate your position).
class BaseModel<T>
{
public virtual T[] Get()
{
// return array of T's
}
public virtual T Find(object param)
{
// return T based on param
}
public virtual T New()
{
// return a new instance of T
}
}
That's your base, and then you have inheritors like:
class DeviceModel : BaseModel<Device>
{
public override Device New()
{
return new Device();
}
}
Now, any generic operations you define in DeviceModel will default to returning or using strongly typed Device. Notice the virtual methods in the BaseModel class. In the base class methods, you might provide some basic operations predicated upon using T's or something. In sub-classes, you can define more specific, strongly typed behavior.
I'd also comment that you might want to pull back a little and consider the relationship of BaseModel and BaseRow. It appears that you're defining a parallel inheritance hierarchy, which can tend to be a code smell (this is where more of your code might have come in handy -- I could be wrong about how you're using this). If your ongoing development prospects are that you're going to need to add a FooRow every time you add a FooModel, that's often a bad sign.
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();
}
}