Unity Container and ContainerControlledLifetimeManager when Service Interface is Array - c#

I have the following method:
public void RegisterPlugin<T1>() where T1 : IWebrolePlugin
{
try
{
_container.RegisterType<T1>(new ContainerControlledLifetimeManager());
_container.RegisterType<IWebrolePlugin, T1>(typeof(T1).Name,new ContainerControlledLifetimeManager());
}catch(Exception e)
{
Trace.TraceError(e.ToString());
}
}
My problem is that when i do _container.Resolve() i get as expected the same instance of SomePlugin, but when using the following injection constructor it resolves new instances.
I have a the following registration also:
_container.RegisterType<WebsiteManager>(new InjectionConstructor(typeof(IDirectoryManager), typeof(IStore), typeof(IWebrolePlugin[])));
My problem is that the array of IWebrolePlugin[] is new instances. Can I do anything such my method
public T GetPlugin<T>() where T : IWebrolePlugin
{
return _container.Resolve<T>();
}
will return the same instances that the WebsiteManager got in its constructor?

When resolving, Unity first maps the interface to the concrete type by name and uses the concrete type and name as the BuildKey. This BuildKey is used for all aspects of constructing and injecting dependencies (including locating a lifetime manager). That is why the default registration (null name) and a named registration of the same type result in different instances being returned.
The easiest way to use the same instance is to align the registration names between the interface and the concrete type:
public void RegisterPlugin<T1>() where T1 : IWebrolePlugin
{
try
{
_container.RegisterType<T1>(typeof(T1).Name,
new ContainerControlledLifetimeManager());
_container.RegisterType<IWebrolePlugin, T1>(typeof(T1).Name);
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
public T GetPlugin<T>() where T : IWebrolePlugin
{
return _container.Resolve<T>(typeof(T).Name);
}
This will result in same instance being returned for a straight Resolve and as part of a ResolveAll (for arrays).

Related

.NET Dependency Injection with generic services that depend on other generic services

Introduction
I started development with C# 2 months ago. Coming from a PHP background using Symfony I have knowledge about dependency injection and love generics so far, but the combination of the two confuses me a bit at the moment.
Concept
I want to use a factory to create a specific instance of an IHandler. The IHandler can receive an IParser<T> which - as you can see - supports generics, so I have one interface for every possible parser. The factory will get a list of IParser which have a SupportsParsing method which will be called inside the factory to get the correct IParser and create a new IHandler with the chosen IParser.
Code
IServiceFactory
public interface IServiceFactory<out T>
{
T Create(string key);
}
EventHandlerFactory
public class EventHandlerFactory<T> : IServiceFactory<IHandler>
{
private readonly IEnumerable<IParser<T>> _parsers;
public EventHandlerFactory(IEnumerable<IParser<T>> parsers)
{
_parsers = parsers;
}
public IHandler Create(string key)
{
foreach (IParser<T> parser in _parsers)
{
if (parser.SupportsParsing(key))
{
return new EventHandler<T>(parser);
}
}
throw new NotImplementedException();
}
}
IParser
public interface IParser<T>
{
List<T> Parse();
bool SupportsParsing(string key);
}
EventCounterParser
public class EventCounterParser : IParser<EventCounter>
{
public List<EventCounter> Parse()
{
throw new System.NotImplementedException();
}
public bool SupportsParsing(string key)
{
throw new System.NotImplementedException();
}
}
EventLevelParser
public class EventLevelParser : IParser<EventLevel>
{
public List<EventLevel> Parse()
{
throw new System.NotImplementedException();
}
public bool SupportsParsing(string key)
{
throw new System.NotImplementedException();
}
}
IHandler
public interface IHandler
{
void Handle();
}
EventHandler
public class EventHandler<T> : IHandler
{
private readonly IParser<T> _parser;
public EventHandler(IParser<T> parser)
{
_parser = parser;
}
public void Handle()
{
throw new System.NotImplementedException();
}
}
Registering the services
So registering the parsers is easy
services.AddScoped<IParser<EventCounter>, EventCounterParser>();
services.AddScoped<IParser<EventLevel>, EventLevelParser>();
Intention
But what I want to do now is:
* Register the service factory
* Register the handlers
* Automatically inject all IParser instances into the EventHandlerFactory
And this is where it's getting hard for me. I don't really know how to register the services when it's using generics inside generics and also how to inject a generic IList or IEnumerable in here.
Attempts
Own attempts
What I tried for the IHandler:
services.AddScoped<IHandler, Handler.Event.EventHandler<EventLevelParser>>();
services.AddScoped<IHandler, Handler.Event.EventHandler<EventCounterParser>>();
services.AddScoped(typeof(IServiceFactory<>), typeof(EventHandlerFactory<>));
Unhandled exception. System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: GenericDITest.Handler.IHandler Lifetime: Scoped ImplementationType: GenericDITest.Handler.Event.EventHa
ndler1[GenericDITest.Parser.Event.EventLevelParser]': Unable to resolve service for type 'GenericDITest.Parser.IParser1[GenericDITest.Parser.Event.EventLevelParser]' while attempting to activate 'GenericDITest.Handler.Event.EventHandler1[GenericDITest.Pa
rser.Event.EventLevelParser]'.) (Error while validating the service descriptor 'ServiceType: GenericDITest.Handler.IHandler Lifetime: Scoped ImplementationType: GenericDITest.Handler.Event.EventHandler1[GenericDITest.Parser.Event.EventCounterParser]': Unab
le to resolve service for type 'GenericDITest.Parser.IParser1[GenericDITest.Parser.Event.EventCounterParser]' while attempting to activate 'GenericDITest.Handler.Event.EventHandler1[GenericDITest.Parser.Event.EventCounterParser]'.)
So I tried to use the type specified registration
services.AddScoped(typeof(IHandler), typeof(Handler.Event.EventHandler<>));
services.AddScoped(typeof(IServiceFactory<>), typeof(EventHandlerFactory<>));
but then I get the error
System.ArgumentException: Cannot instantiate implementation type 'GenericDITest.Handler.Event.EventHandler`1[T]' for service type 'GenericDITest.Handler.IHandler'.
Sadly, I don't know enough about generics to really solve this issue. I don't really understand the error message. Maybe I'm defining the services wrong?
Attempts from other users
Like #user1672994 suggested, I made the following changes
IHandler to IHandler<out T>
EventHandler<T> : IHandler to EventHandler<T> : IHandler<T> EventHandlerFactory<T> : IServiceFactory<IHandler> to EventHandlerFactory<T> : IServiceFactory<IHandler<T>>
public IHandler Create(string key) to public IHandler<T> Create(string key).
Now, I can add the service as services.AddScoped(typeof(IHandler<>), typeof(Handler.Event.EventHandler<>)); which now launches the application without any error, however because of all the generics, I now have to also register my factory like this
services.AddScoped(typeof(IServiceFactory<>), typeof(EventHandlerFactory<>));.
But when I access the factory through var service = provider.GetService(typeof(IServiceFactory<>)); I'm getting a new error. Implementation type 'GenericDITest.Handler.Event.EventHandlerFactory1[T]' can't be converted to service type 'GenericDITest.Service.IServiceFactory1[T]'. But this I don't understand, since it's the same interface?
I also uploaded the project to a file hoster so you can check it out: https://mega.nz/#!jf51UALL!sbVrGSXoTtfzZLzOl9i7wwa-OC5s3xlhuf_RJuorIQs
The EventHandler shall get ANY implementation of IParser
That’s not how generics work though. An IParser<T> is a completely separate type from some IParser. Unless you actually have a type hierarchy between them, they are completely unrelated. Generics can be a bit confusing here because a generic type isn’t actually a type that really exists. It’s only when you apply a concrete generic type argument, that there is a type.
So both IParser<EventLevel> and IParser<EventCounter> are real types (completely separate and unrelated ones though!), but the generic “template” for these types, IParser<T>, is not a concrete type.
You also have to understand that within a generic class, a generic type argument T will always refer to the exact same thing. That is basically a constant type that will be inserted at some point.
So your EventHandlerFactory<T> may have an IEnumerable<IParser<T>> but if you use the factory for example as EventHandlerFactory<EventCounter>, then that type will have an IEnumerable<IParser<EventCounter>>. So that’s also the type it will look for when resolving it via dependency injection. So it cannot get IParser<EventLevel> instances because those are unrelated to the type it is asking for.
An EventHandlerFactory<EventCounter> would only ever inject parsers for EventCounter and not other ones (which may not be what you were trying to do). And instead of using that type to also create handlers for EventLevel, you would have to use a different factory of the type EventHandlerFactory<EventLevel> (which has its own list of parsers for EventLevel).
It’s not entirely clear to me what exactly you are trying to accomplish, especially since your implementations in your example are all empty, but if I were to guess, I would assume that you are just using too many generics here. So starting from the start, these are my assumptions:
You have multiple parsers that can work with different types, but only ever one type per parser.
You have a single event handler type that uses a compatible parser to handle some event of a type.
You want a single factory that allows you to get the right event handler to handle your key.
Now there is a fundamental problem with your approach though: The parsers return a list of a concrete type, e.g. your EventCounterParser returns a list of EventCounter objects. If you now want to use that object within your event handler, then you will need separate event handler types to handle each of those results separately. Otherwise you have no common information to work with within your generic event handler.
What the right solution here is highly depends on what exactly you are trying to do with your parsers and event handlers. With the information we have that’s very difficult to address.
If we were to ignore that part of the parsers though, and the event handlers for example would just utilize the parser in a non-generic way, then you could reduce the setup to the following:
public interface IParser
{
List<object> Parse();
bool SupportsParsing(string key);
}
public class EventHandler : IHandler
{
private readonly IParser _parser;
public EventHandler(IParser parser)
{
_parser = parser;
}
public void Handle()
{ }
}
public class EventHandlerFactory
{
private readonly IEnumerable<IParser> _parsers;
public EventHandlerFactory(IEnumerable<IParser> parsers)
{
_parsers = parsers;
}
public IHandler Create(string key)
{
foreach (var parser in _parsers)
{
if (parser.SupportsParsing(key))
{
return new EventHandler(parser);
}
}
throw new NotImplementedException();
}
}
services.AddScoped<IParser, EventCounterParser>();
services.AddScoped<IParser, EventLevelParser>();
services.AddScoped<EventHandlerFactory>();

Is it possible to override a named registration in Castle Windsor 3?

I have two interfaces, IExampleClient and IServiceUsingClient. Each has two implementations. They are registered in a Castle Windsor installer as follows:
container.Register(Component.For<IExampleClient>()
.ImplementedBy<FirstClient>()
.LifestyleTransient()
.Named("FirstClient"));
container.Register(Component.For<IExampleClient>()
.ImplementedBy<SecondClient>()
.LifestyleTransient()
.Named("SecondClient"));
container.Register(Component.For<IServiceUsingClient>()
.ImplementedBy<FirstService>()
.LifestyleTransient()
.Named("FirstService")
.DependsOn(Dependency.OnComponent(typeof(IExampleClient), "FirstClient")));
container.Register(Component.For<IServiceUsingClient>()
.ImplementedBy<SecondService>()
.LifestyleTransient()
.Named("SecondService")
.DependsOn(Dependency.OnComponent(typeof(IExampleClient), "SecondClient")));
See that both implementations of IServiceUsingClient depend on a different implementation of IExampleClient. To make this work I've used the DependsOn method to ensure a specific named registration is used.
I now have a set of component tests in which I want to mock the IExampleClient implementations. Normally I'd do this by overriding the registration using the IsDefault() option. However, because these are named registrations I can't do this. Castle complains that there's already a registration with the supplied name. However, if I register with a different name then my IServiceUsingClient will get my real implementations, not my mocks.
I'm hoping that I'm overlooking a technique that will achieve my goal without me having to override the entire dependency chain in my tests. Any ideas?
You can override a named registration using an IHandlerSelector. Here's an example. In the unit test you'll see that I'm registering two named implementations for a single dependency (IGreetingProvider- why? IDK.)
I'm then indicating that when another class needs an instance of IGreetingProvider, the instance named "Hello" should be used.
But then I'm registering an IHandlerProvider which intercepts that request and, out of the available registered components, selects the one named "Goodbye" instead.
So in effect this allows me to override what was previously registered with the container.
[TestClass]
public class HandlerSelectorTests
{
[TestMethod]
public void HandlerSelectorOverridesRegistration()
{
using (var container = new WindsorContainer())
{
container.Register(Component.For<IGreetingProvider, Hello>()
.Named("Hello"));
container.Register(Component.For<IGreetingProvider, Goodbye>()
.Named("Goodbye"));
container.Register(Component.For<SaysSomething>()
.DependsOn(Dependency.OnComponent(typeof(IGreetingProvider), "Hello")));
var handlerSelector = new MyHandlerSelector();
container.Kernel.AddHandlerSelector(handlerSelector);
var resolved = container.Resolve<SaysSomething>();
Assert.AreEqual("Goodbye", resolved.SaySomething());
}
}
}
public class MyHandlerSelector : IHandlerSelector
{
public bool HasOpinionAbout(string key, Type service)
{
return key == "Hello";
}
public IHandler SelectHandler(string key, Type service, IHandler[] handlers)
{
return handlers.First(handler => handler.ComponentModel.Name == "Goodbye");
}
}
public class SaysSomething
{
private readonly IGreetingProvider _greetingProvider;
public SaysSomething(IGreetingProvider greetingProvider)
{
_greetingProvider = greetingProvider;
}
public string SaySomething()
{
return _greetingProvider.GetGreeting();
}
}
public interface IGreetingProvider
{
string GetGreeting();
}
public class Hello : IGreetingProvider
{
public string GetGreeting()
{
return "Hello";
}
}
public class Goodbye : IGreetingProvider
{
public string GetGreeting()
{
return "Goodbye"; //Ok, it's not a greeting.
}
}

How pass parameter to ITypedFactory method to more than the immediate class being created

I have the following class hierarchy:
public class FirstProvider : IFirstProvider
{
public FirstProvider (string data, ISecondProvider provider)
{
...
}
}
public class SecondProvider : ISecondProvider
{
public SecondProvider (string data)
{
...
}
}
public interface IProviderFactory
{
T Create<T>(string data) where T : IProvider;
}
IFirstProvider and ISecondProvider both implement IProvider and are registered properly on the container. What I am trying to do is to obtain an instance of FirstProvider from my IProviderFactory like so:
public void DoSomething()
{
var provider = _providerFactory.Create<IFirstProvider>("my data");
}
At this point I receive the following exception:
"Missing dependency.
Component SecondProvider has a dependency on string, which could not be resolved.
Make sure the dependency is correctly registered in the container as a service, or provided as inline argument."
It would appear that Windsor does not pass the parameters of the ITypedFactory through the chain of dependencies it has to resolve to create the instance of the class. Is there another way I can support this design or should I reconsider my design?
It seems that components are not registered correctly for your needs.
Could you provide a block of registration code?
I think you should try "a delegate as component factory" to solve your issue.
There are several overloads that might help you.
Something like this:
container.Register(Component.For<ISecondProvider>().
.UsingFactoryMethod(container =>
{
/* your code */
}));
container.Register(Component.For<IFirstProvider>().
.UsingFactoryMethod(container =>
{
var prvoider = container.Resolve<ISecondProvider>();
/* your code */
}));
Also it is possible to pass arguments when you resolve a type.
There is an answered question "Castle Windsor passing constructor parameters".

Getting a singleton instance using SimpleInjector for a class which implements a generic type, not actually returning a singleton

I've been experiencing some strange code-issues, and finally seem to have noticed that what as supposed to be acting as Singleton, is not actually a singleton. This is a cache-class, so I am ending up having multiple-versions of the same cache. I've written some test-code as per below, and in my eyes this should work. Am I doing anything wrong, or have I stumbled upon a bug?
public class GenericClassesNotRegisteredAsSingletonTest
{
public interface ICacheManager<T> { }
public class SettingsData { }
public class SettingsCache : CacheManager<SettingsData> { }
public class CacheManager<T> : ICacheManager<T> { }
[Test]
public void Test()
{
var container = new Container();
var registration = Lifestyle.Singleton
.CreateRegistration(typeof(SettingsCache),
typeof(SettingsCache), container);
container.AddRegistration(
typeof(ICacheManager<SettingsData>), registration);
container.Verify();
var cache1 = container.GetInstance<SettingsCache>();
var cache2 = container.GetInstance<SettingsCache>();
bool sameRef = cache1 == cache2;
Assert.That(sameRef == true);
}
}
You made the following registration:
_container.AddRegistration(
serviceType: typeof(ICacheManager<SettingsData>),
registration: registration);
And you're doing the following resolve:
_container.GetInstance<SettingsCache>();
You haven't registered SettingsCache explicitly, but only ICacheManager<SettingsData>. Since SettingsCache is a concrete class, Simple Injector will resolve it as transient instance for you.
The solution is to either register SettingsCache explicitly or resolve ICacheManager<SettingsData> instead. You can make a second registration with using the same Registration instance. For instance:
_container.AddRegistration(
serviceType: typeof(SettingsCache),
registration: registration);
The Diagnostic Services will warn you about this this type of misconfiguration.

How to create a fully lazy singleton for generics

I have the following code implementation of my generic singleton provider:
public sealed class Singleton<T> where T : class, new()
{
Singleton()
{
}
public static T Instance
{
get { return SingletonCreator.instance; }
}
class SingletonCreator
{
static SingletonCreator()
{
}
internal static readonly T instance = new T();
}
}
This sample was taken from 2 articles and I merged the code to get me what I wanted:
http://www.yoda.arachsys.com/csharp/singleton.html and
http://www.codeproject.com/Articles/11111/Generic-Singleton-Provider.
This is how I tried to use the code above:
public class MyClass
{
public static IMyInterface Initialize()
{
if (Singleton<IMyInterface>.Instance == null // Error 1
{
Singleton<IMyInterface>.Instance = CreateEngineInstance(); // Error 2
Singleton<IMyInterface>.Instance.Initialize();
}
return Singleton<IMyInterface>.Instance;
}
}
And the interface:
public interface IMyInterface
{
}
The error at Error 1 is:
'MyProject.IMyInterace' 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 'MyProject.Singleton<T>'
The error at Error 2 is:
Property or indexer 'MyProject.Singleton<MyProject.IMyInterface>.Instance' cannot be assigned to -- it is read only
How can I fix this so that it is in line with the 2 articles mentioned above? Any other ideas or suggestions are appreciated.
Does my implementation break the Singleton pattern?
Basically, you've given a class constraint on your singleton class, along with the new() constraint.
When writing
Singleton<IMyInterface>
you're using an interface type as T, which violates the type constraint you defined.
For error 2,
Singleton<IMyInterface>.Instance = CreateEngineInstance();
you're trying to assign a value to a read-only property. So you need to define a setter on your Instance property for that line to work.
Update
Something along these lines should do it for you :
public sealed class Singleton
{
private static Hashtable bindings = new Hashtable();
private static Hashtable instances = new Hashtable();
private static void checkType(Type requested, Type bound)
{
if (requested.IsValueType)
throw new Exception("Cannot bind a value type to a reference type");
// also check type inheritance and other things...
}
private static void checkBinding(Type requested)
{
if (!(bindings.ContainsKey(requested)))
throw new Exception(String.Format("Type {0} was not bound !", requested.FullName));
}
public static void Bind<T, U>() where U : class, new()
{
checkType(typeof(T), typeof(U));
bindings[typeof(T)] = typeof(U);
}
public static T GetInstance<T>()
{
Type requested = typeof(T);
Type bound = (Type) bindings[requested];
checkBinding(requested);
if (!instances.ContainsKey(requested)) {
// We know that type "bound" was set with a new() class constraint
instances[requested] = (T) Activator.CreateInstance(bound);
}
return (T) instances[requested];
}
}
You could then write :
Singleton.Bind<IMyInterface, MyClass>();
IMyInterface instance = Singleton.GetInstance<IMyInterface>();
If you want to go further, you could also specify the lifecycle of the objects created by this provider, so that you could use singletons, or have the provider return a new object for each call, and so on.
You should also take a look at the Dependency Injection pattern, which seems close to what you want achieve, and also look at existing DI frameworks (NInject, Nhibernate) that already do this and much more.
Sure, you have an issue there. You generic is suppose to take class, not interface.
internal static readonly T instance = new T();
Your code suppose to create an instance of that class, you could not instantiate interface type.
So, if you need some type to act as singletone, you should write:
Singleton<MyInterface>.Instance
where
public class MyInterface : IMyInterface { }
Then you don't need to have any 'if' in you code, since it Singleton responsibility to instantite an object and keep it as only one instance.
Not related to question: currently Singletone's are considered by many developers as 'code-smell', so in general you have to avoid them. Try to think you application without Singletone at all.

Categories

Resources