Situation:
I have an interface, such as
public interface ITestClass
{
string StringElement { get; }
}
There is an implementation for it:
public class TestClassImplementor :
ITestClass
{
public string StringElement
{
get { return "AAA"; }
}
}
I do have a factory that creates an implementation instance:
public class TestClassFactory
{
public ITestClass Create()
{
return new TestClassImplementor();
}
}
I want to be able to resolve the implementation using Castle Windsor configuration file (XML), but at the same time not configuring the implementation for the interface.
Why is this needed: resolving (web) services. I do have a (web) service interface, but I don't access the implementation, as it is on another component. I want to be able to simply type MyCastleUtility.Resolve<ITestClass>() and get a prepared web service. I want to use Castle Windsor configuration file (XML) to configure the service I'm trying to access.
The problem: if I can't access the implementation, I can't configure it in the configuration file.
What I've tried so far:
1) Factories.
<component id="mycompfactory"
type="MyTestProject.TestClassFactory, MyTestProject"/>
<component id="mycomp"
type="MyTestProject.ITestClass, MyTestProject"
factoryId="mycompfactory" factoryCreate="Create" />
I do get the:
Castle.MicroKernel.ComponentRegistrationException : Type MyTestProject.INewTestClass is abstract. As such, it is not possible to instansiate it as implementation of MyTestProject.INewTestClass service
2) Proxies. Hit the wall when tried to find a way to configure that "proxy must be created for 'ITestClass' interface".
Target: configure Castle Windsor to create interface implementation without directly accessing the class, that implements the interface.
Help is much appreciated,
Mindaugas
For the factory approach:
Did you also configure the FactoryFacility in your config?
In your "mycomp", I think you want to use "service" and not "type":
<component id="mycomp" service="MyTestProject.ITestClass, MyTestProject" factoryId="mycompfactory" factoryCreate="Create" />
Related
I'm using unity to implement Dependency Injection in my .NET Web Api app.
Here is the relevent part of my WebApiCongig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
AppDependancyRegistry.Register(container);
config.DependencyResolver = new UnityResolver(container);
}
}
And here is my AppDependancyRegistry class
public static class AppDependancyRegistry
{
public static void Register(UnityContainer container)
{
container.RegisterType(typeof(IBaseRepository<>), typeof(BaseRepository<>));
//container.RegisterTypes( AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);
}
}
I have mapped the Generic Repositores but I couldnt get through with registering the Manager classes to its interfaces. I dont want to map every one of Manager classes Manaually.
I have commented the part I have done from all the research. I just want a confirmation, this is how I do it as I cant get my App running now without doing some more of stuff
My manager classes:interfaces looks like
DutyManager: IDutyManager
UserDetailManager:IUserDetailManager
etc. Thanks in Advance
You will need, at some point, to register each of them. However, if you don't want to manually do each and every one of them, what you could "basically" do is, by reflection, load the assembly, iterate over every interface, check how many classes implement that interface, if there is only one, register the interface to that class as an unnamed registration.
Why unnamed? Well, named registration are useless unless you actually use the name in the registration, or in the ResolvedParameter constructor, and since you're not "hand crafting" the registrations, you wouldn't refer to them most likely.
Don't forget though that in your case, since the interface and the classes are generics, you'll need to check the ParameterType too.
I found the solution to this qn. Using Unity we can directly Map all classes to respecive Interfaces by using
container.RegisterTypes( AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);
Here, Unity maps by convention where they map like this
DutyManager: IDutyManager
UserDetailManager:IUserDetailManager
It seems to me that it's a bad idea to have a domain service require an instance of IOptions<T> to pass it configuration. Now I've got to pull additional (unnecessary?) dependencies into the library. I've seen lots of examples of injecting IOptions all over the web, but I fail to see the added benefit of it.
Why not just inject that actual POCO into the service?
services.AddTransient<IConnectionResolver>(x =>
{
var appSettings = x.GetService<IOptions<AppSettings>>();
return new ConnectionResolver(appSettings.Value);
});
Or even use this mechanism:
AppSettings appSettings = new AppSettings();
Configuration.GetSection("AppSettings").Bind(appSettings);
services.AddTransient<IConnectionResolver>(x =>
{
return new ConnectionResolver(appSettings.SomeValue);
});
Usage of the settings:
public class MyConnectionResolver
{
// Why this?
public MyConnectionResolver(IOptions<AppSettings> appSettings)
{
...
}
// Why not this?
public MyConnectionResolver(AppSettings appSettings)
{
...
}
// Or this
public MyConnectionResolver(IAppSettings appSettings)
{
...
}
}
Why the additional dependencies? What does IOptions buy me instead of the old school way of injecting stuff?
Technically nothing prevents you from registering your POCO classes with ASP.NET Core's Dependency Injection or create a wrapper class and return the IOption<T>.Value from it.
But you will lose the advanced features of the Options package, namely to get them updated automatically when the source changes as you can see in the source here.
As you can see in that code example, if you register your options via services.Configure<AppSettings>(Configuration.GetSection("AppSettings")); it will read and bind the settings from appsettings.json into the model and additionally track it for changes. When appsettings.json is edited, and will rebind the model with the new values as seen here.
Of course you need to decide for yourself, if you want to leak a bit of infrastructure into your domain or pass on the extra features offered by the Microsoft.Extensions.Options package. It's a pretty small package which is not tied to ASP.NET Core, so it can be used independent of it.
The Microsoft.Extensions.Options package is small enough that it only contains abstractions and the concrete services.Configure overload which for IConfiguration (which is closer tied to how the configuration is obtained, command line, json, environment, azure key vault, etc.) is a separate package.
So all in all, its dependencies on "infrastructure" is pretty limited.
In order to avoid constructors pollution of IOptions<>:
With this two simple lines in startup.cs inside ConfigureServices you can inject the IOptions value like:
public void ConfigureServices(IServiceCollection services)
{
//...
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
services.AddScoped(cfg => cfg.GetService<IOptions<AppSettings>>().Value);
}
And then use with:
public MyService(AppSettings appSettings)
{
...
}
credit
While using IOption is the official way of doing things, I just can't seem to move past the fact that our external libraries shouldn't need to know anything about the DI container or the way it is implemented. IOption seems to violate this concept since we are now telling our class library something about the way the DI container will be injecting settings - we should just be injecting a POCO or interface defined by that class.
This annoyed me badly enough that I've written a utility to inject a POCO into my class library populated with values from an appSettings.json section. Add the following class to your application project:
public static class ConfigurationHelper
{
public static T GetObjectFromConfigSection<T>(
this IConfigurationRoot configurationRoot,
string configSection) where T : new()
{
var result = new T();
foreach (var propInfo in typeof(T).GetProperties())
{
var propertyType = propInfo.PropertyType;
if (propInfo?.CanWrite ?? false)
{
var value = Convert.ChangeType(configurationRoot.GetValue<string>($"{configSection}:{propInfo.Name}"), propInfo.PropertyType);
propInfo.SetValue(result, value, null);
}
}
return result;
}
}
There's probably some enhancements that could be made, but it worked well when I tested it with simple string and integer values. Here's an example of where I used this in the application project's Startup.cs -> ConfigureServices method for a settings class named DataStoreConfiguration and an appSettings.json section by the same name:
services.AddSingleton<DataStoreConfiguration>((_) =>
Configuration.GetObjectFromConfigSection<DataStoreConfiguration>("DataStoreConfiguration"));
The appSettings.json config looked something like the following:
{
"DataStoreConfiguration": {
"ConnectionString": "Server=Server-goes-here;Database=My-database-name;Trusted_Connection=True;MultipleActiveResultSets=true",
"MeaningOfLifeInt" : "42"
},
"AnotherSection" : {
"Prop1" : "etc."
}
}
The DataStoreConfiguration class was defined in my library project and looked like the following:
namespace MyLibrary.DataAccessors
{
public class DataStoreConfiguration
{
public string ConnectionString { get; set; }
public int MeaningOfLifeInt { get; set; }
}
}
With this application and libraries configuration, I was able to inject a concrete instance of DataStoreConfiguration directly into my library using constructor injection without the IOption wrapper:
using System.Data.SqlClient;
namespace MyLibrary.DataAccessors
{
public class DatabaseConnectionFactory : IDatabaseConnectionFactory
{
private readonly DataStoreConfiguration dataStoreConfiguration;
public DatabaseConnectionFactory(
DataStoreConfiguration dataStoreConfiguration)
{
// Here we inject a concrete instance of DataStoreConfiguration
// without the `IOption` wrapper.
this.dataStoreConfiguration = dataStoreConfiguration;
}
public SqlConnection NewConnection()
{
return new SqlConnection(dataStoreConfiguration.ConnectionString);
}
}
}
Decoupling is an important consideration for DI, so I'm not sure why Microsoft have funnelled users into coupling their class libraries to an external dependency like IOptions, no matter how trivial it seems or what benefits it supposedly provides. I would also suggest that some of the benefits of IOptions seem like over-engineering. For example, it allows me to dynamically change configuration and have the changes tracked - I've used three other DI containers which included this feature and I've never used it once... Meanwhile, I can virtually guarantee you that teams will want to inject POCO classes or interfaces into libraries for their settings to replace ConfigurationManager, and seasoned developers will not be happy about an extraneous wrapper interface. I hope a utility similar to what I have described here is included in future versions of ASP.NET Core OR that someone provides me with a convincing argument for why I'm wrong.
I can't stand the IOptions recommendation either. It's a crappy design to force this on developers. IOptions should be clearly documented as optional, oh the irony.
This is what I do for my configuraition values
var mySettings = new MySettings();
Configuration.GetSection("Key").Bind(mySettings);
services.AddTransient(p => new MyService(mySettings));
You retain strong typing and don't need need to use IOptions in your services/libraries.
You can do something like this:
services.AddTransient(
o => ConfigurationBinder.Get<AppSettings>(Configuration.GetSection("AppSettings")
);
Using Net.Core v.2.2, it's worked for me.
Or then, use IOption<T>.Value
It would look something like this
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
I would recommend avoiding it wherever possible. I used to really like IOptions back when I was working primarily with core but as soon as you're in a hybrid framework scenario it's enough to drive you spare.
I found a similar issue with ILogger - Code that should work across frameworks won't because I just can't get it to bind properly as the code is too dependent on the DI framework.
I'm trying to register multiple implementation of single interface, but I would like to avoid using named type registration. Let's say I'm having following code:
public interface IStorage { ... }
public class DocumentStorage : IStorage { ... }
public class ImageStorage : IStorage { ... }
public interface IRepository { ... }
public class DocumentRepository : IRepository
{
public DocumentRepository(IStorage storage /*, ... and other dependencies */) { ... }
}
And doing all Unity IoC registration on single file. Rest of application does not have access to container (+ service locator pattern is big no no in my code)
Registering this would then look like this:
container.RegisterType<IStorage, DocumentStorage>("document");
container.RegisterType<IStorage, ImageStorage>("image");
container.RegisterType<IRepository, DocumentRepository>(
new InjectionFactory((c, t, s) => new DocumentRepository(
c.Resolve<IStorage>("document") /*, ... resolve other deps here */)));
And here is lying my laziness issue - I really don't want to write resolution of all dependencies this way - this makes IoC hassle. I would have to go trough all registrations depending on one of IStorage implementations and resolve all other dependencies manually.
I was thinking of turned-around solution by registering DocumentStorage resolved by DocumentRepository - which I'm not able to figure out, and moreover, it is putting dependency on another side of "equation" ("register type for being injected to another type" (instead of "register type and let it be resolved if something depends on it")).
Is there any other way how to make registration easier? (I'm not focusing on factory here - I could imagine other non-factory-able usages requiring similar way of registering dependencies)
Thanks for any advice :)
I'd like to use NServiceBus profiles to override the concrete classes used in the Spring.net dependency injection for use in Integration Testing.
In my EndpointConfig class, I have a component being configured:
NServiceBus.Configure.Instance.Configurer.ConfigureComponent<RealCommunicator>(ComponentCallModelEnum.None);
(This bit is OK!)
I created a new profile:
public class StubThirdPartyProfile : NServiceBus.IProfile
{
}
And a behaviour class to implement it:
public class StubThirdPartyBehaviour : IHandleProfile<StubThirdPartyProfile>
{
public void ProfileActivated()
{
Configure.Instance.Configurer.ConfigureComponent<StubCommunicator>(ComponentCallModelEnum.None);
}
}
Both StubCommunicator and RealCommunicator implement the same interface and I was hoping that the profile would remove the old dependency and use the StubCommunicator instead but this is not the case. Is there a way to do this?
When the solution is run, I get the following error:
Spring.Objects.Factory.UnsatisfiedDependencyException:
Error creating object with name 'Namespace.CommandHandler' :
Unsatisfied dependency expressed through object property 'Communicator':
There are 2 objects of Type [Namespace.ICommunicator] for autowire by type,
when there should have been just 1 to be able to autowire property 'Communicator' of object
We're using the Spring.net framework in NServicebus configured as so:
Configure.With().SpringFrameworkBuilder()
.XmlSerializer().Log4Net()
.MsmqTransport()
.IsTransactional(true);
Instead of configuring the real component in the endpoint config class, consider registering it in a class which handles the other NServiceBus profiles - Lite, Integration, Production.
Using Castle Windsor, I want to configure a generic service with a type parameter; and have it implemented by a known concrete type that implements the service with a specific type as the generic parameter. Expressed as a unit test, I would like to get the following to work:
[TestClass]
public class WindsorTests
{
[TestMethod]
public void ResolveGenericEntity_Test()
{
WindsorContainer container = ConfigureContainer();
IEntity<string> entity = container.Resolve<IEntity<string>>();
Assert.IsNotNull(entity);
}
private WindsorContainer ConfigureContainer()
{
WindsorContainer container = new WindsorContainer();
container.AddComponent("entity", typeof(IEntity<>), typeof(ConcreteEntity));
return container;
}
}
public interface IEntity<T> { }
public class ConcreteEntity : IEntity<string> {}
This test fails with the following exception:
System.InvalidOperationException:
WindsorGenericsTest.ConcreteEntity is
not a GenericTypeDefinition.
MakeGenericType may only be called on
a type for which
Type.IsGenericTypeDefinition is true.
Now, I have found a post here describing the same problem. The poster describes how this can be resolved by changing the DefaultGenericHandler.ResolveCore method. However, I don't feel like changing the Castle code itself and running on a custom build.
Does anyone know how I can resolve this problem without modifying the Castle Windsor source code ? I am happy to implement a facility to support this, if that is what is needed.
Will it work if you change the line in ConfigureContainer to this?
container.AddComponent("entity", typeof(IEntity<string>), typeof(ConcreteEntity));