Im trying to seperate my Model,View and ViewModel in different assemblys and instantiate them with Castle Windsor.
I have my app.config
<components>
<component id="ViewModel.SomeViewModel" service="TEST.Business.IViewModel, TEST.Business" type="TEST.ViewModel.SomeViewModel, Test.ViewModel" />
<component id="ViewModel.SomeView" service="TEST.Business.IView, TEST.Business" type="TEST.View.SomeView, Test.View" />
</components>
and resolve it by
IoC.Configure();
var viewModel = IoC.Resolve<IViewModel>();
var view = IoC.Resolve<IView>();
view.ShowDialog();
my static IoC class
public static class IoC
{
private static IWindsorContainer container;
public static void Configure()
{
IResource resource = new ConfigResource("castle");
container = new WindsorContainer(new XmlInterpreter(resource));
}
public static TService Resolve<TService>()
{
return container.Resolve<TService>();
}
}
really simple until yet.
But i would love to do it like this:
naming have to be like this: I[someName]ViewModel and I[someName]View
and then resolve every component in my app.config thus for each pair of View and ViewModel resolve and associate them.
I guess there are many solutions for my problem but i dont know which keywords to use.
btw: I[someName]ViewModel and View are ofc IViewModels and IViews
I think you're doing it wrong.
Do not abstract your views and view models. It gives you no benefit. Therefore the problem is an architectural one, not a technical one.
Use reflection to iterate over the types in the assemblies you want to resolve. You can use Classes for registrations.
var assembly = Assembly.GetExecutingAssembly(); // Replace with the assembly you want to resolve for.
var exports = assembly.ExportedTypes;
var viewTypes = exports.Where(t => t.GetInterface(typeof(IView).FullName) != null);
foreach (var viewType in viewTypes)
{
var viewModelType = assembly.GetType(viewType.FullName.Replace("View", "ViewModel"));
var viewModel = container.Resolve(viewModelType);
var view = container.Resolve(viewType);
view.ShowDialog();
}
In your example, I can't see any dependency between IViewModel and IView so your code doesn't make sense. If the view model is injected as a parameter of the constructor it will be automatically resolved.
I would not recommend doing this technique. It is probably more complicated than it needs to be. Are you sure you really understand how to use an IoC container/Castle Windsor?
Ioc containers are great once you get used to them. In general you only want to use your container from your main/bootstrapping code of your application. To me it seems you try to make the resolve function for the container static to allow resolving compoents anywhere. This should not be required.
If you are looking for a method to bind views and view models in nice way, take a look at caliburn micro. You can combine this with most Ioc containers, including windsor
Kind regards,
Marwijn.
Related
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 have a Generic repository which I want to register for DI, it implements an interface IRepository.
Normally I would create an instance of it like this:
IRepository repo = new Repository<Order>();
However I am trying to get up to speed in .net 5 ahead of release and want to get this working with DI, I have resorted to the following :
services.AddTransient<DAL.IRepository<Models.Order>, DAL.Repository<Models.Order>>();
But this feels wrong, I don't want 50+ lines in there one for each of the classes in my model...
I cannot find anything online about this, I know its possible with other ioc containers.. but as this is a learning project I dont want to use another container, Im aiming to do it all with .net5s native container.
You should be able to register the open generic with
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
After some back and forwards in the comments to other answers I have a working solution, It might not be the best way but it works. Ill update again if I find a better way to implement this.
The two issues I had were : Needed to register a generic interface, the issue here was a lapse in concentration on my part.. I had the syntax wrong for registering a generic type which of course is :
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
The second issue was that I have an assembly which contains 50+ different models which I wanted registered, The way that I addressed this was to write a method that I can pass a list of assemblies to along with the Namespace that I want to register and it iterates over any types that match the criteria and registers them in the DI container.
public void RegisterModels(IServiceCollection services, string[] Assemblies, string #NameSpace)
{
foreach (var a in Assemblies)
{
Assembly loadedAss = Assembly.Load(a);
var q = from t in loadedAss.GetTypes()
where t.IsClass && !t.Name.Contains("<") && t.Namespace.EndsWith(#NameSpace)
select t;
foreach (var t in q.ToList())
{
Type.GetType(t.Name);
services.AddTransient(Type.GetType(t.FullName), Type.GetType(t.FullName));
}
}
}
This is then called from the startup.cs method ConfigureServices :
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<TestContext>(options =>
options.UseSqlServer(#"Server=LOCALHOST\SQLEXPRESS;Database=Test;Trusted_Connection=True;"));
services.AddMvc();
RegisterModels(services, new string[] { "UI" }, "UI.Models");
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
}
There may be a better way to do this, there definitely is using different DI containers, if anyone has improvements to offer please let me know.
You could use a convention based registration library like Scrutor.
Scrutor is a small open source library that provides a fluent API to register services in your Microsoft.Extensions.DependencyInjection container based on conventions (Similar to Autofac's RegisterAssemblyTypes method, StructureMap's Scan method and Ninject's Conventions package).
This will allow you to do something like this:
services.Scan(scan => scan
.FromAssemblies(<<TYPE>>.GetTypeInfo().Assembly)
.AddClasses(classes => classes.Where(x => {
var allInterfaces = x.GetInterfaces();
return
allInterfaces.Any(y => y.GetTypeInfo().IsGenericType && y.GetTypeInfo().GetGenericTypeDefinition() == typeof(IRepository<>)));
}))
.AsSelf()
.WithTransientLifetime()
);
What you can do is create an extension method to encapsulate all those individual items that need to be registered.
That is the same technique Microsoft is using, for example you only put this in startup:
services.AddMvc();
but that is an extension method and behind the scenes you can bet it is registering a bunch of stuff it needs.
so you can create your own extension method like this:
using Microsoft.Extensions.DependencyInjection;
public static IServiceCollection AddMyFoo(this IServiceCollection services)
{
services.AddTransient<DAL.IRepository<Models.Order>, DAL.Repository<Models.Order>>();
//....
return services;
}
and by making the method return the IServiceCollection you make it fluent so you can do
services.AddMyFoo().AddSomeOtherFoo();
Updated based on comment
the other technique to reduce registrations is when your dependency doesn't itself have dependencies you can make the constructor have a default of null so you still have decoupling and could pass a different one in later but the DI won't throw an error and you can just instantiate what you need if it is not passed in.
public class MyFoo(IFooItemDependency myItem = null)
{
private IFooItemDependency internalItem;
public MyFoo(IFooItemDependency myItem = null)
{
internalItem = myItem ?? new FooItemItem();
}
}
I'm not 100% sure on what your question is I assume you don't want to have
services.AddTransient<DAL.IRepository<Models.Order>, DAL.Repository<Models.Order>>();
services.AddTransient<DAL.IRepository<Models.Person>, DAL.Repository<Models.Person>>();
services.AddTransient<DAL.IRepository<Models.Invoice>, DAL.Repository<Models.Invoice>>();
etc
I have done this before (with ninject)
Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
I imagine for Unity you can do something similar like
services.AddTransient<DAL.IRepository<>, typeof(Repository<>)();
And then to use it in a service
public OrderService(IRepository<Models.Order> orderRepository)
{
this.orderRepository = orderRepository;
}
EDIT
As pointed out by OP the correct syntax is:
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
I have a windsor container and windsor doesnt inject my property. The curious thing is with ServiceA the dependency is resolved but not with the component.
Container.AddFacility<WcfFacility>();
Container.Register(Component.For<PublisherService>().AsWcfService());
Container.Register(Component.For<IExecutionProgram>().ImplementedBy<ExecutionProgram>());
Container.Register(Component.For<IValidationProgram>().Instance(Factory.CreateProgramA()));
Container.Register(Component.For<RunnerService>().AsWcfService());
This is my Factory (All the Dependencies implement the same interface and all SubDependencies implement an other shared Interface):
public static class Factory{
public static IValidationProgram CreateProgramA(){
var program = new ValidationProgram(
new DependencyA(
new SubDependencyA(),
new SubDependencyB(),
),
new DependencyB()
);
}
}
In my RunnerService the IExecutionProgram, Property will be resolved.
In my IValidationProgram, I created the IExecutionProgram will not be resolved.
Properties are public in both Implementations.
What did I do wrong?
EDIT:
I added the factory. These Dependencies are all Interfaces and I need specific implementations for a program. So in general I would like to switch easily between programA or programB. I looked into type Facilities like Marwijn supposed, but I cant get the hang of it. How do I use it in my case?
OK I think there is maybe too much information about Castle Windsor because looking for these keywords gives me examples of everything, and frankly I don't understand enough about how it works to properly troubleshoot this. I have tried quite a few permutations with little luck at this point.
I have an IUnitOfWorkFactory that I want to instantiate as a singleton. So, I install Castle Windsor, write a bit of code like so:
iocContainer = new WindsorContainer()
.Install(FromAssembly.This());
var propInjector = iocContainer.Register(
Component.For<IUnitOfWorkFactory>()
.LifestyleSingleton()
.Instance(new NHUnitOfWorkFactory())
);
propInjector.Resolve<IUnitOfWorkFactory>();
This gets called from my Application_Start method.
I have an AccountController wired up like so:
public class AccountController : SecureController
{
public IUnitOfWorkFactory UnitOfWorkFactory { get; set; }
...
...as far as I can figure, this should just "work" (although don't ask me how). But my property is always null when I try to use it.
It seems like I'm missing something silly and simple, but I have no idea what it is.
I have also tried
var propInjector = iocContainer.Register(
Component.For<IUnitOfWorkFactory>()
.ImplementedBy<NHUnitOfWorkFactory>()
.LifestyleSingleton()
);
with no success.
What am I doing wrong?
CONCLUSION
I was missing several steps here. I had built an installer and a bootstrapper per the tutorial, but I registered my services at the wrong spot... before building the controller factory. Now my bootstrapper looks like this:
iocContainer = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(iocContainer.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
iocContainer.Register(
Component.For<IUnitOfWorkFactory>()
.ImplementedBy<NHUnitOfWorkFactory>()
.LifestyleSingleton()
);
... and my property injections were no longer null.... now I just have to debug the other 87 problems...
Both constructor and property injection work when the root object is resolved by the container. In this case, your AccountController would be the root object that Windsor would need to create.
In order to wire this up, you should use a controller factory. Once the controller is registered and resolved by the container, everything should work as you expect.
I'm designing a simple aspects framework using the DynamicProxy stuff and StructureMap and I've run up against an issue. I have the following method in my Registry:
public T AddAspectsTo<T>(T concreteObject)
{
ProxyGenerator dynamicProxy = new ProxyGenerator();
return (T)dynamicProxy.CreateInterfaceProxyWithTargetInterface(typeof(T)
,concreteObject,
new[] { (IInterceptor)new AspectInterceptor(attributeMap) });
}
Which allows me to write code like:
For<ITestClass>().Use<TestClass>().EnrichWith(AddAspectsTo<ITestClass>);
The important thing is that I'm creating a concrete version of AspectInterceptor. In that class I need to grab items from the IoC container, but at this point I don't know about the IContainer object.
I won't need access to the IoC container until the resulting ITestClasses are in use and so the IContainer will have been created, but can't figure out how to grab the instance?
To be clear, I'm talking about cases here where we setup the structuremap container with:
IContainer container = new Container(new ItemWithPropertiesRegistry());
rather than the standard ObjectFactory stuff, which works fine.
The instance to enrich is available via a lambda:
For<ITestClass>().Use<TestClass>().EnrichWith(x => AddAspectsTo<ITestClass>(x));