This project is read-only.

Couldn't figure out how to register generics

Dec 16, 2014 at 11:19 PM
I'm trying to create a framework based on Shortbus. In its test, there's a example using StructureMap

I'm trying to replicate this using SimpleInjector without success.
 ObjectFactory.Initialize(i =>  {  i.Scan(s =>  {
   s.AssemblyContainingType<IMediator>();
   s.TheCallingAssembly();
   s.WithDefaultConventions();
   s.AddAllTypesOf((typeof(IRequestHandler<,>)));
   s.AddAllTypesOf(typeof(INotificationHandler<>));   });

   i.For<IDependencyResolver>()
       .Use(() => DependencyResolver.Current);     });

   ShortBus.DependencyResolver.SetResolver(
        new StructureMapDependencyResolver(ObjectFactory.Container));

   ...
   var mediator = ObjectFactory.GetInstance<IMediator>(); // do work
vs
   var container = new Container();
   
   container.RegisterManyForOpenGeneric(typeof(IRequestHandler<,>),
          typeof(IRequestHandler<,>).Assembly);

   container.RegisterManyForOpenGeneric(typeof(INotificationHandler<>),
          typeof(INotificationHandler<>).Assembly);

    container.Register<IDependencyResolver, 
          SimpleInjectorDependencyResolver>();
    container.Register<IMediator>(
          () => new Mediator(DependencyResolver.Current));

    container.Verify();

    DependencyResolver.SetResolver(
        new SimpleInjectorDependencyResolver(container));

   ...
   var mediator = container.GetInstance<IMediator>();  // do work
But it complains IMediator's constructor parameter DependencyResolver. What do I miss? Thanks
Dec 17, 2014 at 4:10 AM
What's the exact exception message?
Dec 17, 2014 at 3:26 PM
Thanks for the follow up. I think the constructor error on the container was because I tried it in unit testing code and didn't reference the same instance of the container. Once past that, I'm trying to send a simple request like this:
    var query = new Ping { Message = "Ping" };
    var mediator = container.GetInstance<IMediator>();
    var pong = mediator.Request(query);

    public class Ping : IRequest<string>  {
        public string Message { get; set; }    }

    public class PingHandler : IRequestHandler<Ping, string> {
        public string Handle(Ping request)  {
             return request.Message + "Pong";    }   }
and get this error

{"No registration for type IRequestHandler<Ping, String> could be found."}
System.Exception {SimpleInjector.ActivationException}

So looks like my IRequestHanlder registration was wrong too. Since the StructureMap version works, I wonder what the SimpleInjector equivalent of
AddAllTypesOf((typeof(IRequestHandler<,>)));
Thanks.
Dec 17, 2014 at 4:26 PM
The Simple Injector equivalent of AddAllTypesOf((typeof(IRequestHandler<,>)) is:
container.RegisterManyForOpenGeneric(typeof(IRequestHandler<,>), assemblies);
Do note though that you need to supply the assemblies that the RegisterManyForOpenGeneric must look at. It seems that your StructureMap configuration uses two assemblies: typeof(IMediator).Assembly and Assembly.GetExecutingAssembly(). But it seems that you only use one assembly in your Simple Injector registration.

The following should work:
container.RegisterManyForOpenGeneric(typeof(IRequestHandler<,>), typeof(PingHandler).Assembly);
Dec 17, 2014 at 6:17 PM
Edited Dec 17, 2014 at 6:19 PM
Thank you so much! It does live up to it's name as SimpleInjector ^_^
   container = new Container();
   container.RegisterManyForOpenGeneric(
      typeof (IRequestHandler<,>), AppDomain.CurrentDomain.GetAssemblies());
   container.Register<IDependencyResolver, SimpleInjectorDependencyResolver>();
   container.Register<IMediator, Mediator>();
   container.Verify();
Now off to interceptors, which is what attracted me here in the first place.
Dec 17, 2014 at 6:24 PM
>> Now off to interceptors

I hope you meant to say decorators, because Simple Injector highly focuses on decorator support. Although you can do interception with Simple Injector, we -the Simple Injector contributors- promote the use of decorators, because this leads to code that is much cleaner, faster, maintainable, and prevents vendor lock-ins.
Dec 17, 2014 at 7:35 PM
Haha, I was just debating whether I should bother you with another question, because I couldn't intercept and notice the extension says it can only intercept interface, I wonder if intercept PingHandler : IRequestHandler<Ping, string> is possible.

The extension documentation did mention "The decorator pattern ... when it comes to applying cross-cutting concerns, you might end up writing decorators for many service interfaces". I guess the type of generic handler in Shortbus is considered a single interface, therefore free of that side effect?

I'll give decorator another look. Thanks.
Dec 17, 2014 at 7:58 PM
The interception example in the Simple Injector documentation uses .NET's RealProxy class, which is limited to interfaces. If you want to do intercept anything else, you can use Castle Dynamic Proxy, which is easily integrated with Simple Injector. But again, favor decorators over interceptors.

Many developers start using interception because there application is littered with off-by-one interfaces, such as IOrderServices, ICustomerServices, IShippingServices, IPaymentServices, ICustomerRepository, IOrderRepository, ILocationRepository, etc, etc. Because there is no relationship between those interfaces, applying cross-cutting concerns using AOP can only be done using interception (where a class is generated dynamically for you on the background). But the problem is actually in the design of these applications. If you define common generic interfaces for your application's artifacts, you will find that the argument for using interception completely disappears. The ICommandHandler<TCommand> and IQueryHandler<TQuery, TResult> are great examples of this. By using these interfaces you make the role of a certain class very clear and this allows you to define a single generic decorator that can be applied to a wide range of classes in the system (which is what AOP is all about). Of course this limits you to wrapping classes that implement the same interface, but since your application will just have a few of those generic interfaces, this will hardly ever be a problem. And even if you want to apply the same cross-cutting concern around multiple interfaces, the cross-cutting concern can be easily extracted into its own class, that can be reused by the decorators for several abstractions.

It depends on your view whether you see the generic interface as one interface. What the .NET type system is concerned, each closed version of the interface is a completely different interface. And also from your application, an ICommandHandler<MoveCustomer> is something completely different than a ICommandHandler<ShipOrder>. But still they belong to the same group of objects. In languages that don't support generic typing, we would probably define a single non-generic ICommandHandler interface and let all command handlers implement that. I've once saw a video by Robert C. Martin who did this exact thing in Java, but it was ugly because the casts were littered all over the place (it was still SOLID code, but not pretty at all). And applying cross-cutting concerns must be done with much more care, because there's no type information available to apply decorators (or interceptors) conditionally. But from that point of view, you can see all closed versions of that generic interface as one interface, because you can apply the same generic decorator around all of them.

But if you want to apply a decorator to just a single closed implementation, there are several ways to do this. You can for instance implement a non-generic decorator for it:
public class AlwaysPingTwicePingHandlerDecorator : IRequestHandler<Ping, string> {
    private readonly IRequestHandler<Ping, string> decoratee;

    public PingHandlerDecorator(IRequestHandler<Ping, string> decoratee) {
        this.decoratee = decoratee;
    }

    public string Handle(Ping ping) {
        return this.decoratee.Handle(ping) + this.decoratee.Handle(ping);
    }
}

// Register as follows
container.RegisterDecorator(typeof(IRequestHandler<,>), typeof(AlwaysPingTwicePingHandlerDecorator));
Another option is to create a generic decorator and apply it conditionally:
// Only apply to IRequestHandler<Ping, string>
container.RegisterDecorator(typeof(IRequestHandler<,>), typeof(SomeGenericDecorator<,>),
    c => c.ServiceType == typeof(IRequestHandler<Ping, string>));
Dec 17, 2014 at 8:53 PM
Edited Dec 17, 2014 at 8:54 PM
@whoever, see @dot_NETJunkie's articles here and here - the simple idea that having one or two standard interfaces throughout your architecture enables the application of cross cutting concerns (AOP) without "writing decorators for many service interfaces".
Dec 17, 2014 at 9:20 PM
@qujck, I assumed.he was familiar with these articles, since ShortBus seems to be completely designed around these articles.

To me however, it would be unacceptable to let the core of my application completely depend upon an external framework. ShortBus defines these interfaces, but those interfacea should IMO always be part of the application. It is the same sort of vendor lockin we try to prevent with Simple Injector.
Dec 17, 2014 at 9:56 PM
I didn't click on the link before - it really is built on those 2 interfaces!
Dec 17, 2014 at 11:42 PM
I read those two articles many times but never made the connection to SimpleInjector, even though the name dot_NET_Junkie screaming at me every time. Thanks again for the detailed explanation.

I got the idea from using another framework Agatha RRSL. I like two things the most, one is a RequestDispatcher that allows you send a list of different Request and Response in batch, the other is Interceptor where you have access to both Request and Response. It's perfect for hosting an intranet web service, but seems a little heavy as part of an MVC app. I don't like that every interceptor solution depends on Castle dynamic proxy and I'm also trying to pick ShortBus apart, partially because it's a simple framework that I can understand, partially because I have different requirement.

If I use decorator pattern, both handler and decorator need access and modify both request and response. For example, in case of a backend system outage, handler needs to update response to say outage, where AuditingDecorator needs to read both request and response and record UserA access ServiceB result is Failed due to Outage. If caching is done via decorator, it has to update response indicating IsCache=true. In case of RRSL, caching is built into the framework and the "interceptor" has a RequestContext where you can access both Request and Response before and after handling.

This doesn't seem possible with a super generic interface IRequestHandler<in TRequest, out TResponse>. It sounds like I have to create a base Request and Response and let the handler take those, which makes the whole thing closer to the Agatha RRSL, minus dispatcher, interceptor, service hosting, etc

Not sure what I'm going to do. Will keep looking. Really appreciate all the help.
Dec 18, 2014 at 11:53 AM
The patterns described in those articles are general and not really connected to Simple Injector (or even a DI library at all), although we, the creators and maintainers of Simple Injector, do have a preference in these kinds of patterns and architectures, so it's quite obvious that Simple Injector supports this.

In my view there decorators aren't any more limited than interceptors are, so everything you can do with interception can be done using decorators. If you want to change the response of request handler, but don't have any type information available at compile time, you'd use reflection. You would do that both inside your interceptor and inside your decorator.

With interceptors however, everything starts with objects and you would need to do casting or reflection on everything, because your interceptor can be wrapped around anything. With decorators on the other hand you start out with statically typed objects, and I like to keep everything statically typed along the way. This means that you sometimes need to define extra interfaces to keep everything compiling, but this actually makes your code much clearer.

>> In case of RRSL, caching is built into the framework and the "interceptor" has a RequestContext where you can access both Request and Response before and after handling.

So RRSL actually built an API on top of this to get this behavior, but you will still heavily depend on RRSL here, and with decorators you get this behavior for free, because you already have the request and response objects.

For instance, you can do this:
interface IResponse { bool IsCache { get; set; } }
interface IRequestHandler<in TRequest, out TResponse> where TResponse : IReponse { }
With this generic type constraint you can now have a decorator that is completely compile-safe. Of course, the downside is that now each response class needs to implement an IsCache property. It doesn't really matter here that we are using decorators, you need to do the same with interceptors. Of course we can use a base class instead of an IResponse interface, but this solution smells. Why should the request handler implementation know anything about this IsCache property. Is it allowed to set it or not? We are polluting our interface with this. And if every response can be cached, why have this property in there.

Instead, to me this feels like something we need to deal with at a different level. I would suggest having this IsCache set using a contextual property, for instance:
class CachingRequestHandlerDecorator<TRequest, TResponse>
    : IRequestHandler<TRequest, TResponse>
{
    private readonly IRequestHandler<TRequest, TResponse> decoratee;
    private readonly ICache cache;
    private readonly ICachingContext cachingContext;

    // ctor here

    public TResponse Handle(TRequest request) {
        TResponse response;
        if (!this.cache.TryGetValue(request, out response) {
            response = this.decoratee.Handle(request);
            this.cache.Add(request, response);
        } else {
            this.cachingContext.ReturnedFromCache = true;
        }

        return response;
    }
}
The injected ICachingContext is some request-specific implementation (or singleton where the ReturnedFromCache property stores the value in a thread-specific field). By setting the ReturnedFromCache here, we can a different consumer of this interface (higher up the call stack) read this value to determine whether the value was cached or not.

Although you might need some extra infrastructure for this, the important point is that you don't want to pollute your functional API (the request and response objects) with this cross-cutting things.

Does this make sense?
Dec 18, 2014 at 8:16 PM
Edited Dec 18, 2014 at 8:17 PM
I think the exact way I wanted isn't possible in the ShortBus version of the Handler. Most this type of framework looks like this:
   public class PingRequest : Request { public string Message { get; set; } }
   public class PingResponse : Response  { public List<string> Messages { get; set; } }
   public class PingHandler : RequestHandler<PingRequest, PingResponse> {
        public override Response Handle(PingRequest request)  {
            response.Messages.Add(request.Message);
            response.Messages.Add("Pong");
            return response;    }  }
In this case, you have access to Request and Response from the handler, and any decorator/interceptor that wrap around it. But the ShortBus version looks like this
   public class PingRequest : IRequest<List<string>> { public string Message { get; set; } }
   public class PingRequestHandler : IRequestHandler<PingRequest, List<string>> {
        public List<string> Handle(PingRequest request)  {
            List<string> result = new List<string> { request.Message };
            result.Add("pong");
            return result;   }  }
Its IRequestHanlder is just a interface and built dynamically at runtime in Mediator. On the consuming side, it's like
     var query = new PingList { Message = "Ping" };
     var mediator = container.GetInstance<IMediator>();
     var pong = mediator.Request(query);
     Assert.AreEqual(pong.Data.Count, 4);
Here, pong is a concrete Response from the framework, and pong.Data is the TResponse returned from the handler. This saves the hassle creating a response for every request, but probably losing the ability to manipulate base response from handler/decorator.

I'll look at your suggestions and some other framework and try to learn more. Thanks for being so patient helping a beginner.