I have many classes, that have similar operations of mapping objects. To keep code dry I want to create base abstract class for all these classes.
base abstract class would have generic mapping function like this:
public TEntity GetEntity(Result<TServiceClientEntity> res)
{
entity = MappingProfiles.TryMap(res.Value);
//some logic with result here
return entity;
}
Result class:
public class Result<T>
{
public T Value{ get; set; }
//some more properties..
}
But the problem is that I can't think a way of how to map generic classes like that:
public static class MappingProfiles
{
public static T2 TryMap<T,T2>(T t)
{
return (T2)Map((Real_T_type)t); //f.e.: the type is ExampleFrom
}
public static ExampleTo Map(ExampleFrom from)
{
return new ExampleTo
{
exapleValue = from.exapleValue
};
}
}
EDIT:
I also want that TryMap generic method use my predefined Map manual methods for mapping.
You can use Reflection (C#) to accomplish such things:
public static TOut Map<TIn, TOut>(TIn source)
where TOut : new()
{
var inPropDict = typeof(TIn).GetProperties()
.Where(p => p.CanRead)
.ToDictionary(p => p.Name);
var outProps = typeof(TOut).GetProperties()
.Where(p => p.CanWrite);
var destination = new TOut();
foreach (var outProp in outProps) {
if (inPropDict.TryGetValue(outProp.Name, out var inProp)) {
object sourceValue = inProp.GetValue(source);
if (inProp.PropertyType != outProp.PropertyType) {
sourceValue = Convert.ChangeType(sourceValue, outProp.PropertyType);
}
outProp.SetValue(destination, sourceValue);
}
}
return destination;
}
Reflection enables you to inspect a type and to get its properties, fields, etc.
Type.GetProperties() returns an array of PropertyInfo with name, type, and other information about a property. It also allows you to read from or to write to a property of an object.
The code above is just a quick and dirty example without exception handling. It does only a flat mapping and does not map collections or nested objects.
It also could be improved by allowing you to declare mappings for properties not having the same name etc.
There is a tool doing all these things and more called AutoMapper.
Solution with manual mapping methods
I suggest defining an interface like this
public interface IMapper<T1, T2>
{
T2 Map(T1 input);
}
Example of a concrete implementation:
public class ExampleFromToMapper : IMapper<ExampleFrom, ExampleTo>
{
public ExampleTo Map(ExampleFrom input)
{
return new ExampleTo {
ExampleValue = input.ExampleValue
};
}
}
The idea is to use dependency injection to do the job of selecting the right mapper.
You can use the NuGet package Microsoft.Extensions.DependencyInjection as an example. But many other dependency injection frameworks exist.
Write a method configuring the mappers (as extension method in this example):
public static IServiceCollection AddMappers(this IServiceCollection services)
{
return services
.AddSingleton<IMapper<ExampleFrom, ExampleTo>, ExampleFromToMapper>()
.AddSingleton<IMapper<OtherFrom, OtherTo>, OtherFromToMapper>();
}
Define the container somewhere:
public static class Config
{
public static ServiceProvider Container { get; set; }
}
And at startup of your application configure the container
var services = new ServiceCollection();
services
.AddMappers()
.AddTransient<MyForm>(); // See below
Config.Container = services.BuildServiceProvider();
As an example, let us assume that you have a WinForms app with a form defined like this (it uses a mapper directly, but instead it could use other services that do use mappers. The DI container resolves the dependencies recursively and injects them in the constructors automatically):
public partial class MyForm : Form
{
private readonly IMapper<ExampleFrom, ExampleTo> _mapper;
public MyForm(IMapper<ExampleFrom, ExampleTo> mapper)
{
_mapper = mapper;
InitializeComponent();
}
}
Now, you can start the application like this:
var frm = Config.Container.GetRequiredService<MyForm>();
Application.Run(frm);
Okay, at the beginning it looks complicated, but once you have set up the basics it becomes easy to add new services. Every class offering some functionality is considered a service.
Solution with manual static mapping methods.
To make classes easier testable (or for some others reasons), generic mapper can be static too.
Thanks to Oliver Jacot-Descombes answer I created this solution:
//This works like static class.
public class MappingProfiles
{
//Constructor needs to be private, so that class work like static class.
private MappingProfiles() { }
private static readonly MappingProfiles _instance = new MappingProfiles();
//We need instance to invoke this class methods.
public static MappingProfiles Instance { get { return _instance; } }
public static TResult? TryMap<TSource, TResult>(TSource source)
where TResult : new()
where TSource : class, new()
{
//Trying to get mapper for result.
var resultMapper = typeof(MappingProfiles).GetMethods().FirstOrDefault(m =>
m.ReturnType == typeof(TResult) &&
m.GetParameters()[0].ParameterType == typeof(TSource));
if (resultMapper is null)
throw new Exception($"Mapper not found. From: {typeof(TSource)}, to: {typeof(TResult)}");
//Makes TSource array, because Invoke method works only with arrays.
TSource[] sources = new TSource[] { source };
//Calls manual mapping method.
object res = resultMapper.Invoke(MappingProfiles.Instance, sources);
return (TResult)res;
}
public static ExampleTo Map(ExampleFrom from)
{
return new ExampleTo
{
//...
};
}
}
To call this mapper:
var mapped = MappingProfiles.TryMap<TExampleFrom, TExampleTo>(exampleFromVariable);
Related
Given the following code (which I know won't compile and isn't correct):
public abstract class Fetcher {
public abstract IEnumerable<object> Fetch();
}
public class Fetcher<T> : Fetcher {
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
public IEnumerable<T> Fetch() => _fetcher(); // override or new
}
And this example setup:
var myFetchers = new List<Fetcher> {
new Fetcher<string>(() => new List<string> { "white", "black" })),
new Fetcher<int>(() => new List<int> { 1, 2 }))
};
How can I structure my code so that this will work?
IEnumerable<IEnumerable<object>> fetcherResults =
myFetchers.Select(fetcher => fetcher.Fetch()); // get objects from derived method
TLDR; I've thought about this a little more. A different way to state my question is: how do I run the Fetch method on all the items in the myFetchers list and save a collection of their results, without having to determine the base type of each item and do a cast to that type, while not returning IEnumerable<object> from the Fetch method itself?
The key here is that at the time the objects of different generic type are in a collection of the parent type, I want to run the derived type's method, but return the result as IEnumerable<object>, not IEnumerable<T>. (This can be done using a different method if necessary, I suppose, though it would be nice if it were the same name.) This is so that a section of the code that doesn't need to know about fetchers can have its data (and just be passed fetcherResults), but the part of the code that does care about fetchers can completely ignore what type of data the fetchers work with (not its concern, only the consumer of the data needs to work with the specific types).
I don't have to use inheritance here, and interface IFetcher would work just as well. I keep thinking about how explicit interface implementation might help, but I'm just not closing the loop right now how to make this work for me:
// in a class implementing ICollection<T>
public IEnumerator<T> GetEnumerator() => _collection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable) _collection).GetEnumerator();
As usual, the real situation is more complicated than this (such as the data the fetchers are providing coming from a database, etc.). But getting this one part down will be all I need.
I have looked at the following resources to no avail: implement an inheritable method that returns an object, call method on generic type from abstract parent.
There is a straight-forward way to do this with explicit implementation as you suspected. This is only available if you use an interface rather than an abstract class.
public interface IFetcher {
IEnumerable<object> Fetch();
}
public class Fetcher<T> : IFetcher {
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
IEnumerable<object> IFetcher.Fetch() => Fetch().Cast<object>();
public IEnumerable<T> Fetch() => _fetcher();
}
In this implementation, the interface version of the call returns IEnumerable<object>, while the class-accessible version returns the more specific IEnumerable<T>. If you call the fetcher through the interface, it will resolve to the first. Calling through the class will resolve to the second.
If I understand the question correctly, then you can solve the problem by making Fetcher<T> implement a generic interface IFetcher<T> like this:
public interface IFetcher<T>
{
IEnumerable<T> Fetch();
}
public class Fetcher<T> : IFetcher<T>
{
private readonly Func<IEnumerable<T>> _fetcher;
public Fetcher(Func<IEnumerable<T>> fetcher) { _fetcher = fetcher; }
public IEnumerable<T> Fetch() => _fetcher();
}
And then creating an adapter that can convert IFetcher<TFrom> to an IFetcher<TTo> like this:
public class Adaptor<TFrom, TTo> : IFetcher<TTo>
{
private readonly IFetcher<TFrom> _fetcher;
public Adaptor(IFetcher<TFrom> fetcher)
{
_fetcher = fetcher;
}
public IEnumerable<TTo> Fetch()
{
return _fetcher.Fetch().Cast<TTo>();
}
}
This allows for example to convert from IFetcher<string> to IFetcher<object>.
With the help of this extension method:
public static class ExtensionMethods
{
public static Converter<TFrom> Convert<TFrom>(this IFetcher<TFrom> fetcher)
{
return new Converter<TFrom>(fetcher);
}
public class Converter<TFrom>
{
private readonly IFetcher<TFrom> _fetcher;
public Converter(IFetcher<TFrom> fetcher)
{
_fetcher = fetcher;
}
public IFetcher<TTo> To<TTo>()
{
return new Adaptor<TFrom, TTo>(_fetcher);
}
}
}
You can do something like this easily:
static void Main(string[] args)
{
var myFetchers = new List<IFetcher<object>>
{
new Fetcher<string>(() => new List<string> { "white", "black" }).Convert().To<object>(),
new Fetcher<int>(() => new List<int> { 1, 2 }).Convert().To<object>()
};
var results = myFetchers.Select(x => x.Fetch());
}
Please note that you can do without the extension method, but it will make your code more readable.
I am trying to build out a structure where I have a base IValidator<> interface that will be generated for our system based on some metadata. We want to give future developers the flexibility to 1) Regenerate the concrete implementations of IValidator<> if need be without disturbing any hand-written code and 2) Add decorators to IValidator<> to be able to extend the functionality without disturbing the auto-generated code.
I would like to have some way to resolve the generic decorators at runtime using the RegisterDecorator method of Simple Injector so our dev team does not need to go and update the composition root every time we add a decorator.
Here are some example classes/interfaces
public interface IValidator<T> where T : class
{
void Validate(T entity);
}
public class ClientValidator : IValidator<Client>
{
public void Validate(Client entity)
{
//Auto-generated
}
}
public class UserValidator : IValidator<User>
{
public void Validate(User entity)
{
//Auto-generated
}
}
public class ClientValidatorDecorator : IValidator<Client>
{
private readonly IValidator<Client> clientValidator;
public ClientValidatorDecorator(IValidator<Client> clientValidator)
{
this.clientValidator = clientValidator;
}
public void Validate(Client entity)
{
//New rules
this.clientValidator.Validate(entity);
}
}
public class UserValidatorDecorator : IValidator<User>
{
private readonly IValidator<User> userValidator;
public UserValidatorDecorator(IValidator<User> userValidator)
{
this.userValidator = userValidator;
}
public void Validate(User entity)
{
//New rules
this.userValidator.Validate(entity);
}
}
public class ValidationContext
{
private readonly IValidator<Client> client;
private readonly IValidator<User> user;
public ValidationContext(IValidator<Client> client, IValidator<User> user)
{
this.client = client;
this.user = user;
}
}
We I am trying to do something like so:
public void RegisterServices(Container container)
{
container.Register(typeof(IValidator<>), AssemblyManifest.GetAssemblies());
container.RegisterDecorator(typeof(IValidator<>), GetType, Lifestyle.Transient, UseType);
}
private static Type GetType(DecoratorPredicateContext ctx)
{
//Return appropriate Decorator
}
private static bool UseType(DecoratorPredicateContext ctx)
{
//Predicate
}
Unfortunately, unless I resolve a concrete type RegisterDecorator throws an error, so resolving another generic seems out. I am not sure how to proceed. Is there a way to do something like this? Is there a better way to get the intended functionality without decorators? We were thinking partial classes, but that has its own set of issues.
Any help will be appreciated!
Rather than plugging in decorators you could use a Composite Validator to enable the addition of IValidator<> implementations as required. This solution would allow the code to contain multiple IValidator<>'s for the same type.
Internally your code will still be able to depend on a single IValidator<T> which would resolve to the CompositeValidator that would call zero or more validators depending on what has been registered in the container at runtime.
The composite validator:
public class CompositeValidator<T> : IValidator<T>
{
public readonly IEnumerable<IValidator<T>> validators;
public CompositeValidator(IEnumerable<IValidator<T>> validators)
{
this.validators = validators;
}
public void Validate(T item)
{
foreach(var validator in this.validators)
{
validator.Validate(item);
}
}
}
The container is configured like this:
var assemblies = new[] { typeof(IValidator<>).Assembly };
var container = new Container();
container.RegisterCollection(typeof(IValidator<>), assemblies);
container.Register(typeof(IValidator<>), typeof(CompositeValidator<>));
where the assemblies variable contains all the assemblies you want to search for validators.
When you resolve IValidator<User> using container.GetInstance<IValidator<User>>() or through constructor injection you get back CompositeValidator<User> which internally references any and all IValidator<User>'s.
The way to get decorators of a type using batch registration is by calling the GetTypesToRegister method overload that accepts a TypesToRegisterOptions object. This way you can instruct SI to return decorators as well.
container.Register(typeof(IValidator<>), assemblies);
var t1 = container.GetTypesToRegister(typeof(IValidator<>), assemblies);
var t2 = container.GetTypesToRegister(typeof(IValidator<>), assemblies,
new TypesToRegisterOptions { IncludeDecorators = true });
foreach (Type t in t2.Except(t1)) {
container.RegisterDecorator(typeof(IValidator<>), t);
}
Do note that I do not suggest using this code. #qujck's answer addresses the design issue you have with your code, and his solutions therefore brings you to a much better place.
This blog post describes a nice alternative to the Repository pattern.
https://cuttingedge.it/blogs/steven/pivot/entry.php?id=92
Instead of Repositories the author recommends the use of Commands and Queries. The particular blog post describes the implementation of the Query part in .NET/C#.
There are two interfaces for the query and for the query handler:
public interface IQuery<TResult>
{
}
public interface IQueryHandler<TQuery, TResult> where TQuery : IQuery<TResult>
{
TResult Handle(TQuery query);
}
He also offers an example for each:
public class FindUsersBySearchTextQuery : IQuery<User[]>
{
public string SearchText { get; set; }
public bool IncludeInactiveUsers { get; set; }
}
public class FindUsersBySearchTextQueryHandler
: IQueryHandler<FindUsersBySearchTextQuery, User[]>
{
private readonly NorthwindUnitOfWork db;
public FindUsersBySearchTextQueryHandler(NorthwindUnitOfWork db)
{
this.db = db;
}
public User[] Handle(FindUsersBySearchTextQuery query)
{
return (
from user in this.db.Users
where user.Name.Contains(query.SearchText)
select user)
.ToArray();
}
}
The query handler can be provided as a constructor parameter to a MVC controller.
public class UserController : Controller
{
IQueryHandler<FindUsersBySearchTextQuery, User[]> handler;
public UserController(IQueryHandler<FindUsersBySearchTextQuery, User[]> handler)
{
this.handler = handler;
}
public View SearchUsers(string searchString)
{
var query = new FindUsersBySearchTextQuery
{
SearchText = searchString,
IncludeInactiveUsers = false
};
User[] users = this.handler.Handle(query);
return this.View(users);
}
}
The author uses the dependency injection container Simple Injector to register all IQueryHandler's at once:
container.RegisterManyForOpenGeneric(
typeof(IQueryHandler<,>),
typeof(IQueryHandler<,>).Assembly);
My question is: How can I do this last statement in Unity?
I'm using Unity 3.5.
I'm able to register each QueryHandler manually, like this:
container.RegisterType<IQueryHandler<FindUsersBySearchTextQuery, User[]>,
FindUsersBySearchTextQueryHandler>();
This works fine but I don't want to add a new mapping each time a new QueryHandler comes up. I want to set up all mappings with one convention which includes future QueryHandler's. Unity 3.5 offers a convention based registration workflow but I could not make it work for my case. I tried this but unfortunately it does not generate the mappings in question.
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default);
If you are going to have many specific implementations of IQueryHandler<,> and not one generic version, then you can't use open generics to register. But you can use reflection to find all implementations and register them each. (This is what RegisterTypes does behind the scenes for you).
You were close with your attempt at the RegisterTypes call in the question, but you used WithMappings.FromMatchingInterface. This will only register classes with their interface that matches by the naming convention of MyClass : IMyClass (prepending an 'I' to the class name). If you instead register with WithMappings.FromAllInterfaces you will get the registrations you are after.
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromAllInterfaces,
WithName.Default);
If you need to only register those classes, you can filter down the classes to only those that implement the interface you are after...
public static class EnumerableTypeExtensions
{
public static IEnumerable<Type> WhichImplementsInterface<T>
(this IEnumerable<Type> types)
{
return types.WhichImplementsInterface(typeof (T));
}
public static IEnumerable<Type> WhichImplementsInterface
(this IEnumerable<Type> types, Type interfaceType)
{
return types.WhichImplementsInterface(interfaceType.Name);
}
public static IEnumerable<Type> WhichImplementsInterface
(this IEnumerable<Type> types, string interfaceTypeName)
{
return types.Where(t => t.GetInterface(interfaceTypeName) != null);
}
}
Then you can use these filters like this...
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().WhichImplementsInterface(typeof(IQueryHandler<,>)),
WithMappings.FromAllInterfaces,
WithName.Default);
I want to create a Shim for an Generic Method. But I have a bit a trouble with the Generic in that case.
Here is my example:
class BaseRepository <T> where T: Entity
{
public T[] FindAll()
{
return Method<T>.FindAll()
}
}
class ClassA : base<A>
{
}
class A : Entity
{
}
class ClassB : base<B>
{
}
class B : Entity
{
}
now I want to create a ShimMethod for ClassA and ClassB
ShimBaseRepository<A>.AllInstances.FindAll = (repo) => MethodA();
ShimBaseRepository<B>.AllInstances.FindAll = (repo) => MethodB();
public A MethodA()
{
//Make the Same as MethodB
}
public B MethodB()
{
//Make the Same as MethodA
}
But what if I have mor than 20 "Base" classes? I don't want to create a Delegate/method for every baseClass. I tried something like this:
List<Type> allEntityClasses = (from x in Assembly.GetAssembly(typeof(Entity)).GetTypes()
where !x.IsAbstract && !x.IsInterface
select x).ToList();
foreach(Type type in allEntityClasses=
{
ShimBaseRepository<type????>.AllInstances.FindAll = (repo) => Method();
}
public Entity????? Method()
{
}
In my Unittest I will use the following methods:
ClassA.FindAll()
ClassB.FindAll()
and not:
Base.FindAll()
Edit:
I use Microsoft Fakes,so I can't Change anything in the ShimClass. Here is the generated sourcecode from Shim.
public class ShimBaseRepository<T> : ShimBase<BaseRepository<T>> where T : Entity
{
public static class AllInstances
{
public static FakesDelegates.Func<BaseRepository<T>, T[]> FindAll { [ShimMethod("FindAll", 20)] set; }
}
}
My intention is, that I don't want to create a delegate for every entity, I just want to iterate through all my EntityClasses and create the delegate dynamically. But I have no Idea how I add my Type object in the
ShimBase<T>
Okay, let's discuss this a little.
First of all, here is a straight-forward solution with virtual method:
public class Base<T> where T : Entity
{
public virtual T[] FindAll()
{
return null;
}
}
Then just override FindAll in concrete classes
Or, if you can, make Base abstract and InnerFindAll abstract too.
But, if you need to specify delegate in runtime (as i can see you have a specific Helper for it, but i can't get, why you invoke helper in Base and then you have some undefined in question AllInstances with a Func) this approach won't help. You'll need to implement Strategy pattern with some default strategy assigned in Base. Then you'll have 3 ways to "resolve" strategies in concrete classes:
Hardcode a strategy in constructor of concrete class
Inject strategy to concrete class constructor via DI container
Implement some kind of Mapper which'll return you appropriate Strategy for EntityType (T)
Also, i think you have some troubles with design. I don't see any reason you need to implement FindAll as a lambda injected to a static property of type Func<T> (yep, i think you can replace AllInstances.FindAll with just a static FindAll). So if i were you, i'd use abstract method..
EDIT
Now i got your problem and can give you only a rather ugly solution via reflection... I hoghly don't recomend you to use this since it's really rigour
public class Program
{
static void Main(string[] args)
{
List<Type> allEntityClasses = (from x in Assembly.GetAssembly(typeof(Entity))
.GetTypes().Where(t=>typeof(Entity).IsAssignableFrom(t))
where !x.IsAbstract && !x.IsInterface
select x).ToList();
foreach (var type in allEntityClasses)
{
var genericType = typeof(BaseGeneric<>).MakeGenericType(type);
var helper = new DelegateHelper();
var myLambda = helper.GetLambdaForType(type);
var allInst = genericType.GetProperty("AllInstances").GetValue(null);
if (allInst == null)
{
allInst = Activator.CreateInstance(genericType.GetProperty("AllInstances").PropertyType);
}
allInst.GetType().GetProperty("FindAll").SetValue(allInst,myLambda);
}
}
}
public static class BaseGeneric<T>
{
public static AllInstances<T> AllInstances { get; set; }
}
public class AllInstances<T>
{
public Func<T[]> FindAll { get; set; }
}
public class DelegateHelper
{
public Delegate GetLambdaForType(Type type)
{
var funcType = typeof(Func<>).MakeGenericType(type.MakeArrayType());
var methodInfo = typeof(DelegateHelper).GetMethods().FirstOrDefault(t => t.Name == "FunctionMethod")
.MakeGenericMethod(type);
var #delegate = methodInfo.CreateDelegate(funcType, this);
return #delegate;
}
public T[] FunctionMethod<T>()
{
return new T[10];
}
}
public class Entity
{
}
public class EntityFirst
{
}
public class EntitySecond
{
}
Validation Rule Contract:
public interface IValidationRule
{
bool IsValid();
}
Concrete Validation Rule:
public class MyClass : IValidationRule
{
public bool IsValid()
{
return true;
}
}
Composite:
public class ValidationRuleComposite : IValidationRule
{
private readonly IEnumerable<IValidationRule> _validationRules;
public ValidationRuleComposite(IEnumerable<IValidationRule> validationRules)
{
_validationRules = validationRules;
}
public bool IsValid()
{
return _validationRules.All(x => x.IsValid());
}
}
When I ask the containter for IValidationRule I want to get ValidationRuleComposite. If I ask the container for a list of IValidationRule I want to get all implementations of IValidationRule except of the ValidationRuleComposite.
How can I achieve this with Ninject?
First you want to set up the bindings for the IEnumerable<IValidationRule> that will be injected into the composite. You can just bind them individually:
// Bind all the individual rules for injection into the composite
kernel.Bind<IValidationRule>().To<MyClass>().WhenInjectedInto<ValidationRuleComposite>();
kernel.Bind<IValidationRule>().To<RuleTwo>().WhenInjectedInto<ValidationRuleComposite>();
Or you can also setup the IEnumerable fairly easy with the convention binding extensions, so that you don't have to add a separate binding for each individual concrete rule. Just be sure to add the Exlcuding clause for the composite class like so:
using Ninject.Extensions.Conventions;
// Bind all the non-composite IValidationRules for injection into ValidationRuleComposite
kernel.Bind(x => x.FromAssemblyContaining(typeof(ValidationRuleComposite))
.SelectAllClasses()
.InheritedFrom<IValidationRule>()
.Excluding<ValidationRuleComposite>()
.BindAllInterfaces()
.Configure(c => c.WhenInjectedInto<ValidationRuleComposite>()));
In my example the composite and the rest of the concretes are in the same assembly, but obviously you can vary your convention binding if they're somewhere else.
Finally, we need to set up the binding so that everywhere else an IValidationRule is request, Ninject provides the composite. There doesn't seem to be an elegant method existing for this, so I wrote my own When clause to avoid the cyclical injection:
// Now bind the composite to the interface for everywhere except itself
kernel.Bind<IValidationRule>().To<ValidationRuleComposite>()
.When(x => x.Target == null
|| x.Target.Member.ReflectedType != typeof(ValidationRuleComposite));
With the help of Soldarnal I came to the following solution:
public static class KernelExtensions
{
public static void BindComposite<TComposite, TCompositeElement>(this StandardKernel container) where TComposite : TCompositeElement
{
container.Bind(x => x.FromAssemblyContaining(typeof(TComposite))
.SelectAllClasses()
.InheritedFrom<TCompositeElement>()
.Excluding<TComposite>()
.BindAllInterfaces()
.Configure(c => c.WhenInjectedInto<TComposite>()));
container.Bind<TCompositeElement>().To<TComposite>()
.When(IsNotCompositeTarget<TComposite>);
}
private static bool IsNotCompositeTarget<TComposite>(IRequest x)
{
if (x.Target == null)
return true;
return x.Target.Member.ReflectedType != typeof(TComposite);
}
}
Usage:
var container = new StandardKernel();
container.BindComposite<ValidationRuleComposite, IValidationRule>();
Here I'm assuming that you want all the validation rules and not a partial list of them, as per the more generic pattern.
I would slightly change the Composition class so that you can do a
kernel.Get<IValidationRuleComposite>()
and a
kernel.GetAll<IValidationRule>()
A simple example follows.
The interfaces
public interface IValidationRule
{
bool IsValid();
}
public interface IValidationRuleComposite : IValidationRule
{
void ValidationRuleCompose(List<IValidationRule> validationRules);
}
and the rules
public class MyClass1 : IValidationRule
{
public bool IsValid()
{
Debug.WriteLine("Valid 1");
return true;
}
}
public class MyClass2 : IValidationRule
{
public bool IsValid()
{
Debug.WriteLine("Valid 2");
return false;
}
}
The composite rule
public class ValidationRuleComposite : IValidationRuleComposite
{
private List<IValidationRule> _validationRules;
public void ValidationRuleCompose(List<IValidationRule> validationRules)
{
_validationRules = _validationRules.Union(validationRules).ToList();
}
public ValidationRuleComposite()
{
_validationRules = new List<IValidationRule>();
}
public bool IsValid()
{
Debug.WriteLine("Composite Valid");
return _validationRules.All(x => x.IsValid());
}
}
and a main
StandardKernel kernel = new StandardKernel();
kernel.Bind<IValidationRule>().To<MyClass1>();
kernel.Bind<IValidationRule>().To<MyClass2>();
kernel.Bind<IValidationRuleComposite>().To<ValidationRuleComposite>();
IValidationRuleComposite try1 = kernel.Get<IValidationRuleComposite>();
IEnumerable<IValidationRule> rules = kernel.GetAll<IValidationRule>();
foreach(IValidationRule trycomp in rules)
{ Debug.WriteLine("trycomp: " + trycomp.GetType().ToString()); trycomp.IsValid(); };
try1.ValidationRuleCompose(rules.ToList());
Console.WriteLine("{0}",try1.IsValid());
Debug.WriteLine("try1: " + try1.GetType().ToString());
EDIT
Equivalent alternative, preserving your composite constructor
public interface IValidationRuleCompositeConstr : IValidationRule
{
}
public class ValidationRuleCompositeOriginal : IValidationRuleCompositeConstr
{
private readonly IEnumerable<IValidationRule> _validationRules;
public ValidationRuleCompositeOriginal(IEnumerable<IValidationRule> validationRules)
{
_validationRules = validationRules;
}
public bool IsValid()
{
return _validationRules.All(x => x.IsValid());
}
}
with corresponding usage:
StandardKernel kernel = new StandardKernel();
kernel.Bind<IValidationRule>().To<MyClass1>();
kernel.Bind<IValidationRule>().To<MyClass2>();
kernel.Bind<IValidationRuleCompositeConstr>().To<ValidationRuleCompositeOriginal>();
IEnumerable<IValidationRule> rules = kernel.GetAll<IValidationRule>();
Ninject.Parameters.ConstructorArgument therules = new Ninject.Parameters.ConstructorArgument("therules", rules);
IValidationRuleCompositeConstr try2 = kernel.Get<IValidationRuleCompositeConstr>(therules);
Debug.WriteLine("Second Class");
Debug.WriteLine (string.Format("{0}",try2.IsValid()));
I don't know how you could do that directly with Ninject, but you could use Ninject to create a class which then creates your validation rules.
public class ValidationRuleFactory : IValidationRuleFactory
{
public IValidationRule CreateComposite()
{
var rules = CreateRules();
return new ValidationRuleComposite(rules);
}
private IEnumerable<IValidationRule> CreateRules()
{
//return all other rules here.
//I would hard code them and add new ones here as they are created.
//If you don't want to do that you could use reflection.
}
}
as this class doesn't hold any state you can then create it with singleton scope.
kernel.Bind<IValidationRuleFactory>().To<ValidationRuleFactory>().InSingletonScope();
Then you inject this class and use it to create your composite
public class MyClass()
{
private readonly IValidationRuleFactory _validationRuleFactory;
public MyClass(IValidationRuleFactory validationRuleFactory)
{
_validationRuleFactory = validationRuleFactory;
}
public bool CheckValid()
{
var composite = _validationRuleFactory.CreateComposite();
return composite.IsValid();
}
}
You wire up your concrete instances of ValidationRule in Ninject, like this.
this.Kernel.Bind<ValidationRule1>().ToSelf();
this.Kernel.Bind<ValidationRule2>().ToSelf();
this.Kernel.Bind<IValidationRule>().To<ValidationRuleComposite>()
.WithConstructorArgument("validationRules",
new IValidationRule[] {
this.Kernel.Get<ValidationRule1>(),
this.Kernel.Get<ValidationRule2>()
});
Now, whenever you have a service that takes an IValidationRule in its constructor, you will get the ValidationRuleComposite concrete type with both ValidationRule1 and ValidationRule2 injected.
As far as I know, Ninject doesn't play nice when it comes to injecting multiple instances of the same type. In this case, we avoid doing that so resolving IValidationRule always results in the composite type.
However, you could build your own scanning convention using Reflection that automatically finds all of the types, excludes any that have the suffix "Composite" in the name, then loops through the types to first bind them to self and then create an array of instances to inject. Have a look at this example of a custom scanning implementation, and its usage.