I have a Service that need inject more than one provider, see below for example. How to use Unity to implement this feature?
public class MyService: IMyService
{
public MyService(IEnumerable<Provider> Providers);
}
I know this is an old question, but maybe this will help someone else that stumbles upon this.
As long as you register the implementations with a specific name, this is possible to easily inject. You will then get all registered implementations.
public class MyService: IMyService
{
public MyService(IProvider[] providers)
{
// Do something with the providers
}
}
Just make sure to inject them as an array. Unity will understand this. And when you register them you can register them as such:
container.RegisterType<IProvider, FooProvider>("Foo");
container.RegisterType<IProvider, BarProvider>("Bar");
One way is to inject the UnityContainer itself, and then resolve all the Providers you need:
public class MyService : IMyService
{
public class MyService(IUnityContainer iocContainer)
{
var providers = iocContainer.ResolveAll<IProvider>();
}
}
The only thing you will need to do is register the UnityContainer with itself somewhere on setup:
unityContainer.Register<IUnityContainer>(unityContainer, new ContainerControllerLifetimeManager());
Related
In the pre-GA version of Service Fabric I was registering a custom serializer like this:
protected override IReliableStateManager CreateReliableStateManager()
{
IReliableStateManager result = new ReliableStateManager(
new ReliableStateManagerConfiguration(
onInitializeStateSerializersEvent: InitializeStateSerializers));
return result;
}
private Task InitializeStateSerializers()
{
StateManager.TryAddStateSerializer(new KFOBinarySerializer());
return Task.FromResult(false);
}
However, the CreateReliableStateManager method was removed in the GA version. I've struggled to get something working in its place. Currently I'm calling
StateManager.TryAddStateSerializer(new KFOBinarySerializer());
from within the service's RunAsync method, which appears to work fine.
What is the recommended way to register a custom serializer?
TryAddStateSerializer is deprecated. Anyone know if this is because custom serialization support will go away or if it will simply be supported through some other mechanism?
You can create the state manager in the StatefulService's constructor (full example here):
class MyService : StatefulService
{
public MyService(StatefulServiceContext serviceContext)
: base(serviceContext, CreateReliableStateManager()) { }
private static IReliableStateManager CreateReliableStateManager() { ... }
}
Regarding the deprecated API, Microsoft says it's safe to use, but it will change in the future.
I need to modify an existing web app to use Castle.Windsor as IOC container. It was originally developed with StructureMap.
I am stuck with the following problem.
Lets say I have registered a couple of interfaces and their corresponding implementations:
IFoo -> Foo
IBar -> Bar
Calling container.Resolve<IFoo>() or container.Resolve<IBar>() works just fine. This means that the services are registered correctly.
I have a Web Api class with dependencies on other services, such as IFoo
public class BadRequestErrorHandler : HttpErrorHandler
{
// services
public BadRequestErrorHandler(IFoo foo) {...} // has dependency on IFoo
}
In StructureMap I can call:
var test = ObjectFactory.GetInstance<BadRequestErrorHandler>();
this will resolve the IFoo dependency.
Now this does not work with windsor.
How can this be achieved with windsor?
Thanks!
* EDIT *
I was just able to make it work by explicitely registering the BadRequestErrorHandler.
container.Register(Component.For<BadRequestErrorHandler>());
I am just hoping there is a better way to achieve this, that does not involve registering classes that have dependencies. I have a bunch of them...
* EDIT 2 **
To ease the pain, I added a special method to deal with these concrete types.
public T GetInstanceWithAutoRegister<T>()
{
if (container.Kernel.GetHandler(typeof(T)) == null)
{
container.Register(Component.For<T>());
}
return container.Resolve<T>();
}
public object GetInstanceWithAutoRegister(Type pluginType)
{
if (container.Kernel.GetHandler(pluginType) == null)
{
container.Register(Component.For(pluginType));
}
return container.Resolve(pluginType);
}
not ideal, but at least better than having to explicetly register each type. Hope someone has a better solution
You can achieve what you want by registering an ILazyComponentLoader which is a hook that gets called by Windsor as a "last resort" when a component cannot be resolved.
In your case, the implementation would probably look somewhat like this:
public class JustLetWindsorResolveAllConcreteTypes : ILazyComponentLoader
{
public IRegistration Load(string key, Type service)
{
return Component.For(service);
}
}
-and then it should be registered as such:
container.Register(Component.For<ILazyComponentLoader>()
.ImplementedBy<JustLetWindsorResolveAllConcreteTypes>());
You can read more about it in the docs.
In my GWT application i'm trying to setup a DI mechanism wihich would allow me to have all the commonly necessary stuff at hand everywhere. I'm using google-gin which is an adaptation of guice for GWT. I have an injector interface defined as this:
#GinModules(InjectionClientModule.class)
public interface MyInjector extends Ginjector {
public PlaceController getPlaceController();
public Header getHeader();
public Footer getFooter();
public ContentPanel getContent();
public EventBus getEventBus();
public PlaceHistoryHandler getPlaceHistoryHandler();
}
My injection module is this:
public class InjectionClientModule extends AbstractGinModule {
public InjectionClientModule() {
super();
}
protected void configure() {
bind(Header.class).in(Singleton.class);
bind(Footer.class).in(Singleton.class);
bind(ContentPanel.class).in(Singleton.class);
bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
bind(PlaceController.class).toProvider(PlaceControllerProvider.class).asEagerSingleton();
bind(PlaceHistoryHandler.class).toProvider(PlaceHistoryHandlerProvider.class).asEagerSingleton();
}
}
When calling MyInjector injector = GWT.create(MyInjector.class); i'm gettign the following exception:
java.lang.NullPointerException: null
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBinding(BindingsProcessor.java:498)
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBindingForUnresolved(BindingsProcessor.java:290)
at com.google.gwt.inject.rebind.BindingsProcessor.createImplicitBindingsForUnresolved(BindingsProcessor.java:278)
at com.google.gwt.inject.rebind.BindingsProcessor.process(BindingsProcessor.java:240)
at com.google.gwt.inject.rebind.GinjectorGeneratorImpl.generate(GinjectorGeneratorImpl.java:76)
at com.google.gwt.inject.rebind.GinjectorGenerator.generate(GinjectorGenerator.java:47)
at com.google.gwt.core.ext.GeneratorExtWrapper.generate(GeneratorExtWrapper.java:48)
at com.google.gwt.core.ext.GeneratorExtWrapper.generateIncrementally(GeneratorExtWrapper.java:60)
at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:647)
at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:78)
at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:268)
at com.google.gwt.dev.shell.ShellModuleSpaceHost.rebind(ShellModuleSpaceHost.java:141)
at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:585)
at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:455)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)
at com.google.gwt.core.client.GWT.create(GWT.java:97)
The problem is that the PlaceController class actually depends on one of the other dependencies. I've implemented it's provider like this:
public class PlaceControllerProvider implements Provider<PlaceController> {
private final PlaceController placeController;
#Inject
public PlaceControllerProvider(EventBus eventBus) {
this.placeController = new PlaceController(eventBus);
}
#Override
public PlaceController get() {
return placeController;
}
}
what should i change for this to work?
Old question but having the same problem I kept falling here. I finally found the way to know which class is messing during ginjection.
When I launch my app in development mode and put stack to Trace, I noticed there is a step called : "Validating newly compiled units".
Under this, I had an error but I didn't notice it since I had to expand 2 nodes which weren't even in red color.
The error was "No source code available for type com.xxx.xxxx ...", which was due to a bad import on client side which couldn't be converted to Javascript.
Hope this may help other here !
While I'm not actually seeing how the errors you're getting are related to the PlaceController being injected, I do see that the provider is returning a singleton PlaceController even if the provider were not bound as an eager singleton or in a different scope. The correct way to write that provider would be:
public class PlaceControllerProvider implements Provider<PlaceController> {
private final EventBus eventBus;
#Inject
public PlaceControllerProvider(EventBus eventBus) {
this.eventBus = eventBus;
}
#Override
public PlaceController get() {
return new PlaceController(eventBus);
}
}
Let guice handle the scoping i.e. "Letting guice work for you".
Other than that, I almost bet that your problem is due to the use of asEagerSingleton. I recommend you try this with just in(Singleton.class) and I further posit that you didn't really need the singleton to be eager. It seems others had problems with the behavior too, there's some indication that it has to do with overusing asEagerSingleton or misunderstanding the #Singleton annotation in a few cases.
I also got a lot of NullPointerException warnings using GIN 1.x with no real explanation of what happened. When I upgraded to gin 2.0 I was told with high accuracy what the error was. You might be helped by upgrading to the 2.0 version that was released a year after you asked this question.
Had the same problem problem, same trace, and the error was that I used "server" classes in my "client" classes, so GIN can't find these classes.
I mean by "server" and "client" the packages in my project.
Hope this could help
Is there a better way to hook up dependencies??
This relies on the singleton App.Current and exposing a function that exposes the _container.SatisfyImports.
Is there a more MEF-tastic way of doing things?
Here is part of my main application class
public partial class App : Application
{
private CompositionContainer _container;
....
public void SatisfyImportsOnce(Object satifyMe)
{
_container.SatisfyImportsOnce(satisfyMe);
}
}
Here is a test class instantiated long after ComposeParts is called...
public class TestClass
{
public TestClass()
{
Console.WriteLine("Created a TestClass");
((Microsoft.Samples.XFileExplorer.App)App.Current).SatisfyImportsOnce(this);
}
}
I am in a similar situation in a WPF application where I want the MainWindow instance to import MEF exports. Since MEF does not create the MainWindow instance, it will not satisfy the imports unless you tell it to.
The way you are doing it will work if you do not want your instance to be registered for recomposition. If you do want recomposition, you should call ComposeParts.
Recomposition will update the imports in your class if and when they change.
Can you import using a class that inherits from Lazy rather than Lazy itself? I am exporting using a derivitive of ExportAttribute that contains metadata.
[FeatureExport(/* Feature Metadata Parameters */)]
public class Feature : IFeature
{
// Feature Properties
}
public class FeatureReference : Lazy<IFeature, IFeatureMetadata>
{
}
public class Consumer
{
[ImportMany]
public IEnumerable<FeatureReference> FeatureReferences { get; set; }
}
Is this possible? Would it work? I could try it myself, but I'm in development so I don't actually have any code written.
No, it won't work I'm afraid. You would need to implement your own programming model extension (either a custom part/catalog or possibly via ReflectionModelServices) to make this work.
MEF would have to create the FeatureReference object in order to set it, and considering that FeatureReference might have any constructor imaginable, you can guess why this isn't supported.