WCF Attribute injection using an IOC Container - wcf

Using ASP.NET MVC I am able to replace the FilterProvider as so
var oldProvider = FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider);
FilterProviders.Providers.Remove(oldProvider);
FilterProviders.Providers.Add(new CustomFilterProvider(_container));
Using my own custom provider. It does not give me the ability to use a factory pattern to create the controller filter attributes but I do get the ability to use property injection to set dependencies the attributes may need using the container.
Is it possible to do something similar using WCF so that I can inject dependencies (property injection is fine) into my user defined classes that derive from Attribute that I use on my service methods (the services are created using IOC)?
I am using CastleWindsors WcfFacility, but a generalised solution (that applied to any container) would probably be a better answer.

One way to do this is to use the containers OnCreate method or similar and do something like the following at registration
Container.Register(Component.For<IMyService>().ImplementedBy<MyService>().OnCreate(WireUpAttibutes).LifeStyle.Transient);
then have the following methods
private static void WireUpAttibutes<T>(IKernel kernel, T instance) {
var attributes = instance.GetType().GetCustomAttributes(typeof(MyAttribute), false);
foreach (var attribute in attributes) {
WireUp(kernel, attribute.GetType(), attribute);
}
}
private static void WireUp(IKernel kernel, Type type, object instance) {
var properties = type.GetProperties().Where(p => p.CanWrite && p.PropertyType.IsPublic);
foreach (var propertyInfo in properties.Where(propertyInfo => kernel.HasComponent(propertyInfo.PropertyType))) {
propertyInfo.SetValue(instance, kernel.Resolve(propertyInfo.PropertyType), null);
}
}

Related

Adding DbContext for list of context types at runtime

To implement a plug-in system in a AspNet Core Mvc app, I would like a non-generic method to add a data context from a list of assemblies loaded dynamically at runtime, taking a Type parameter like this:
foreach(Type tp in pluginContexts)
{
services.AddDbContext(tp, options => ...);
}
instead of the usual
services.AddDbContext<PluginDataContext>(options => ...);
That's because for dynamically loaded assemblies, I can not provide the TContext type parameter to the AddDbContextPool method, since that's statically compiled and not available at compile time.
Background
This is for a larger Asp.Net Core MVC app. The plugins must be able to both access the main database of the overall app and a separate database of their own.
Plugin assemblies, containing domain code and their private database context are to be dropped in a specified directory.
The main app loads the plugin assembly dynamically upon startup.
The way I am solving this now is to have each controller get the IConfiguration instance injected, obtain the appropriate connection string from the config, and the database context is instantiated in the controller. Not so nice but does work.
One can easily inject a general class into the Services collection with AddScoped<>, and then use it as a sort of ServiceLocator - however, that is considered an antipattern.
I looked into the source code for AddDbContext but honestly I am lost.
Is there any simple way to achieve this?
Solved it by creating an extensibility point in the plugin assembly.
Define an interface in the main app, which all plugins must implement.
public interface IPluginContextRegistration
{
void RegisterContext(ref IServiceCollection services, Action<DbContextOptionsBuilder> optionsAction);
String GetDatabaseName();
}
Create a class implementing this interface (in the plugin). It has access to the type of its private database context, thus can use the generic AddDbContext method:
public class DatabaseRegistration : IPluginContextRegistration
{
public void RegisterContext(ref IServiceCollection services, Action<DbContextOptionsBuilder> optionsAction)
{
services.AddDbContext<Test1DbContext>(optionsAction);
}
public String GetDatabaseName()
{
return "test-plugin-db";
}
}
Then in the main app ASP.Net Startup.cs file, add following code, which calls the RegisterContext() method for each plugin. For example, if you want to use Sql Server:
void RegisterPluginDbContexts(ref IServiceCollection services, List<Assembly> assemblyList)
{
IEnumerable<IPluginContextRegistration> registrars = new List<IPluginContextRegistration>();
foreach (Assembly assembly in assemblyList)
{
registrars = registrars.Concat(GetClassInstances<IPluginContextRegistration>(assembly));
}
foreach (var reg in registrars)
{
String name = reg.GetDatabaseName();
String connStr = Configuration.GetConnectionString(name);
reg.RegisterContext(ref services, options => options.UseSqlServer(connStr));
}
}
For completeness - the method "GetClassInstances" is just a helper method using Reflection to obtain an instance of classes implementing the specified interface.
So it's simple after all - no need for re-writing framework code .

Property Injection in Microsoft.Extensions.DependencyInjection

I am relatively new to working with DI containers and have hit a bit of a roadblock.
SimpleInjector has a method with the following signature:
Container.RegisterInitializer<TService>(Action<TService>)
In our code base we do use it like this:
// this is a property injection of the abstract file system
container.RegisterInitializer<IFileSystemInjection>(
fs => fs.FileSystem = new FileSystem());
I am wondering how I would achieve the same using the IServiceCollection parameter in the ConfigureServices method in the Startup.cs class. So far I have been able to register all my types using the services.AddTransient(); but I am not sure how what the equivalent simpleinjector.RegisterInitializer is within the IServiceCollection.
You'd use the factory overload(s) of AddSingleton, AddScoped, and AddTransient. I'm not sure what scope IFileSystemInjection should be in, but it sounds like something that could be a singleton. If not, change the method you call appropriately:
service.AddSingleton<IFileSystemInjection>(p =>
{
var fs = new FileSystemInjection();
fs.FileSystem = new FileSystem();
});
In short, if you provide a factory, then you're responsible for the entire object initialization, hence the new FileSystemInjection(), which I'm subbing as the actual implementation of IFileSystemInjection your using.
If that implementation has dependencies that need to be injected in order to create it, you can pull those from p, which is an instance of IServiceProvider:
var myDep = p.GetRequiredService<MyDep>();
var fs = new FileSystemImplementation(myDep);
You can use this nuget package, that extends standard Microsoft Dependency Injection and adds property injection:
https://www.nuget.org/packages/DJMJ.Extensions.DependencyInjection.Property/1.1.0
Mark property for injection
using Microsoft.Extensions.DependencyInjection;
public class FooService
{
[Inject]
public IBooService BooService { get; set; }
public void Foo()
{
// just start using injected property
BooService...
}
}
Add services scan method in ConfigureServices
using Microsoft.Extensions.DependencyInjection;
...
host.ConfigureServices((services)=>
{
services.AddTransient<IBooService, BooService>();
services.AddTransient<IFooService, FooService>();
// scan method
services.AddPropertyInjectedServices();
});
If you using this extension in asp net and want add property injection support in controllers too, you should add in ConfigureServices this statement:
services.AddControllers().AddControllersAsServices()

Injecting IOptions<> into ApiKeyAuthorizeAttribute

I am using options pattern that stores different configurations, including API keys for different environments. So far I have been using it fine and injecting my values into classes as needed.
However, I faced a little challenge while trying to setup authorization in the controller and run validation against my ApiKey that is unique per environment, because I was not able to inject IOptions into ApiKeyAuthorizeAttribute class to perform validation.
Here is how my controller looks like now:
[ApiKeyAuthorize]
public class NotificationSettingsController : Controller
{
//some endpoints here
}
ApiKeyAuthorize Class:
public class ApiKeyAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//////This...
private readonly IOptions<MyConfig> _config;
public ApiKeyAuthorizeAttribute(IOptions<MyConfig> config)
{
_config = config;
}
/////////...is what I am trying to accomplish
public void OnAuthorization(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
var foundApiKeys = request.Headers.TryGetValue("ReplaceWithOptionsApiKeyName", out var requestApiKeys);
if (!foundApiKeys || requestApiKeys[0] != "ReplaceWithOptionsApiKeyValue")
{
context.Result = new UnauthorizedResult();
}
}
}
My problem is that injecting here isn't possible, but I need to get a value from IOptions<> to run ApiKey validation.
Attributes are constructed in-place, so it's not possible to inject dependencies into them. However, ASP.NET Core provides a workaround. Instead of applying the attribute directly, you can use the ServiceFilter attribute instead and pass it the type of the filter you want to apply:
[ServiceFilter(typeof(ApiAuthorizeAttribute))]
This will dynamically apply the filter to the controller/action while instantiating it with any dependencies it requires at the same time. However, it does limit you in the other direction. For example, if you need to do something like:
[ApiAuthorizeAttribute(Roles = "Admin")]
It would not be possible to achieve this with the ServiceFilter attribute, because you cannot pass property values, like Roles here, along with the type.

NInject: Create instances per user/session on convention binding

In summary:
I've undefined of unknowed IProducerPlugin implementations on several assemblies located on a plugins folder.
I've a Core object stores a list of current registered users.
Core is Composition Root.
So, I need:
To create as many IProducerPlugin inherited class objects as the number of registered users.
When a new user is un/registered I need to create / release these objects.
In order to register my "plugins":
this.Kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(Extensibility.IProducerPlugin))
.BindAllInterfaces());
I'm not quite figuring out how to implement this.
Could you help me please?
I'll appreciate a LOT your help.
DI containers in general and Ninject in special are not suitable to add and remove new bindings to the container during runtime. Some, like Autofac, don't even allow adding bindings once the container is created.
Ninject allows adding new bindings at any time, but you cannot, ever, remove them (*from some use cases there's Rebind, but that's not the same).
kernel.Release(object) is not removing the binding, it's only removing all references to the object that it holds.
For example:
var foo = new object();
kernel.Bind<object>().ToConstant(foo);
to allow garbage collecting of foo you can do one of the following:
kernel.Release(foo);
kernel.Dispose(); kernel = null;
and exactly this is what kernel.Release(...) is for. Maybe you could also Release a singleton and thus force ninject to create a new one on the next request. But i don't know whether this really works, and if it does, it certainly is quite an unexpected hack.
So what you should do is manage the list/dictionary yourself. You can bind and inject the list/dictionary/manager what ever you call it using ninject, but you cannot have ninject manager the list itself.
I've managed to do something like that similar using this a IBindingGenerator interface method...
I've used .BindWith<>() binding method...
this.Kernel.Bind(b => b.FromAssembliesMatching("*")
.SelectAllClasses()
.InheritedFrom(typeof(Extensibility.IProducerPlugin))
.BindWith<PluginBindingGenerator<Extensibility.IProducerPlugin>>()
);
I've implemented a IBindingGenerator:
public class PluginBindingGenerator<T> : IBindingGenerator
{
public System.Collections.Generic.IEnumerable<Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, Ninject.Syntax.IBindingRoot bindingRoot)
{
if (type != null && !type.IsAbstract && type.IsClass && typeof(T).IsAssignableFrom(type))
{
Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object> syntax = bindingRoot.Bind(typeof(Extensibility.IProducerPlugin)).ToProvider(new PluginProvider());
yield return (Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>)syntax;
}
}
}
public class PluginProvider : IProvider<object>
{
private System.Collections.Generic.Dictionary<Domain.Identity.ClientIdentity, Extensibility.IProducerPlugin> plugins;
And then, the provider:
public PluginProvider()
{
this.plugins = new System.Collections.Generic.Dictionary<Domain.Identity.ClientIdentity, Extensibility.IProducerPlugin>();
}
public object Create(IContext ctx)
{
//... I don't know what to do here...
return objects;
}
public Type Type
{
get { throw new NotImplementedException(); }
}
}

How to Implement Castle Windsor IScopeAccessor to provide NHibernate Session Per ViewModel using LifestyleScoped

I am looking for some help creating an implementation of IScopeAccessor, or finding a new solution, that will allow me to provide an NHibernate session per ViewModel.
I know that Windsor now supports scoped lifestyles as seen (here). However the example creates the special scope with a using block and calling container.resolve within the using.
_container.Register(Component.For<A>().LifestyleScoped());
using (_container.BeginScope())
{
var a1 = _container.Resolve<A>();
var a2 = _container.Resolve<A>();
Assert.AreSame(a1, a2);
}
I can't think of a way to make this work because I don't want to pass around the container and I want the scope to be tied to the ViewModel that gets created, which will happen dynamically as they are needed.
As an alternative it looks like I can create an implementation of IScopeAccessor which, according to Krzysztof Koźmic (here) would allow me to
"... provide any scope you like. Scope is an abstract term here and it can be anything."
Unfortunately I cannot find an implementation of IScopeAccessor that isn't specific to a web based scenario and I am struggling to understand exactly what I need to do to turn "anything" into a valid scope.
I have found an example of exactly what I want to do using Ninject (http://www.emidee.net/index.php/2010/08/23/ninject-use-one-database-session-per-view-model/):
Bind<ISession>().ToMethod(ctx =>
{
var session = ctx.Kernel.Get<....>().BuildSessionFactory().OpenSession();
return session;
})
.InScope(context =>
{
var request = context.Request;
if (typeof(IViewModel).IsAssignableFrom(request.Service))
return request;
while ((request = request.ParentRequest) != null)
if (typeof(IViewModel).IsAssignableFrom(request.Service))
return request;
return new object();
});
In Ninject, the InScope indicates that any instances created by the binding should be reused as long as the object returned by the call back remains alive. Essentially, this call back returns the root level ViewModel (since ViewModels can be nested).
Any thoughts on how I can do the same thing or get the same result using Windsor?
The problem seems to be the place of creation.
If it's all about dependencies of viewmodels being constructed, you could maybe use boud lifestyle, as described in What's new...
Or you could alternatively use your own scope accessor, that is sensitive to viewmodels. for example like this:
public class ViewModelScopeAccessor : IScopeAccessor
{
private IDictionary<Guid, ILifetimeScope> scopes = new Dictionary<Guid, ILifetimeScope>();
private ILifetimeScope defaultScope;
public ViewModelScopeAccessor()
: this(new DefaultLifetimeScope())
{ }
public ViewModelScopeAccessor(ILifetimeScope defaultScope)
{
this.defaultScope = defaultScope;
}
public ILifetimeScope GetScope(CreationContext context)
{
var creator = context.Handler.ComponentModel.Implementation;
var viewModel = creator as IViewModel;
if (viewModel != null)
{
ILifetimeScope scope;
if (!scopes.TryGetValue(viewModel.UID, out scope))
{
scope = new DefaultLifetimeScope();
scopes[viewModel.UID] = scope;
}
return scope;
}
else
{
return defaultScope;
}
}
public void Dispose()
{
foreach (var scope in scopes)
{
scope.Value.Dispose();
}
defaultScope.Dispose();
scopes.Clear();
}
}
for the following viewmodel interface :
public interface IViewModel
{
string DisplayName { get; }
Guid UID { get; }
}
You of course could compare the viewmodels in other ways, it's just an example.
The drawback of both, the bound lifestyle and that scope accessor, is, that it won't work, if you use a typed factory inside your viewmodel, to lazily construct objects, since the scope accessor has no idea, from which object/method its factory method was called. But I think is is a general .NET issue, since a method does actually never know, from where it has been called.
So, you could then use your own factories, that produce only one instance per factory instance and make them scoped to your viewmodels too.
Hope this helps.