AutoFac - Instantiating an unregistered service with known services - ioc-container

Instantiating an unregistered service with known services (injecting them via ctr).
I want to avoid container pollution.

Here is another way to resolve unregistered concrete types from container. Note that all autofac constructor finding and selecting logic, all registration event handlers remain in force.
First, you define this method:
public static object ResolveUnregistered(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters)
{
var scope = context.Resolve<ILifetimeScope>();
using (var innerScope = scope.BeginLifetimeScope(b => b.RegisterType(serviceType)))
{
IComponentRegistration reg;
innerScope.ComponentRegistry.TryGetRegistration(new TypedService(serviceType), out reg);
return context.ResolveComponent(reg, parameters);
}
}
The idea is that you get component registration from derived context and resolve it in the current context.
Then you can create some handy overloads:
public static object ResolveUnregistered(this IComponentContext context, Type serviceType)
{
return ResolveUnregistered(context, serviceType, Enumerable.Empty<Parameter>());
}
public static object ResolveUnregistered(this IComponentContext context, Type serviceType, params Parameter[] parameters)
{
return ResolveUnregistered(context, serviceType, (IEnumerable<Parameter>)parameters);
}
public static TService ResolveUnregistered<TService>(this IComponentContext context)
{
return (TService)ResolveUnregistered(context, typeof(TService), Enumerable.Empty<Parameter>());
}
public static TService ResolveUnregistered<TService>(this IComponentContext context, params Parameter[] parameters)
{
return (TService)ResolveUnregistered(context, typeof(TService), (IEnumerable<Parameter>)parameters);
}

I found a solution that required some custom code. Somethings are specific to my app, but I think you can get the picture.
Resolve(parameter.ParameterType) would be a call to your container.
public object ResolveUnregistered(Type type)
{
var constructors = type.GetConstructors();
foreach (var constructor in constructors)
{
try
{
var parameters = constructor.GetParameters();
var parameterInstances = new List<object>();
foreach (var parameter in parameters)
{
var service = Resolve(parameter.ParameterType);
if (service == null) throw new NopException("Unkown dependency");
parameterInstances.Add(service);
}
return Activator.CreateInstance(type, parameterInstances.ToArray());
}
catch (NopException)
{
}
}
throw new NopException("No contructor was found that had all the dependencies satisfied.");
}

Here is a way to resolve an unregistered type with know constructor (ctor) properties. This is based on a previous great post: https://stackoverflow.com/a/6994144/2641447.
In this solution, it is absolutely great that constructor finding and selecting logic is handled by Autofac.
The comment is referred to dispose issues what I have solved with the 'ExternallyOwned()' wich configure the component so that instances are never disposed by the container.
I think that an improvement of the solution may be the following:
public static object ResolveUnregistered(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters)
{
var scope = context.Resolve<ILifetimeScope>();
using (var innerScope = scope.BeginLifetimeScope(b => b.RegisterType(serviceType).ExternallyOwned()))
return innerScope.Resolve(serviceType, parameters);
}
The usings:
using Autofac;
using Autofac.Core;
using System;
using System.Collections.Generic;

Related

Mediatr Scope problems

I am using Mediatr to handle messages from a queue. I can get a simple example to work. However I have run into problems when I try to inject an object into my handler
public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
{
private IMyDependency myDependency;
public MessageCommandHandler(IMyDependency myDependency)
{
this.myDependency = myDependency;
}
public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
}
This only works when I register IMyDependency as a transient scope, however when I register it as scoped lifetime it fails with the error
Cannot resolve 'MediatR.IRequestHandler`2[MyNamespace.MessageCommand,System.Boolean]' from root provider because it requires scoped service 'MyNamespace.IMyDependency'
I need to be able to inject dependencies with scoped lifetime. Has anyone got a solution for this.
I am using the .NET Core dependency injection framework. It is setup as follows
services.AddHostedService<QueueConsumer>();
services.AddScoped<IMyDependency, MyDependency>();
services.AddMediatR(new Assembly[] { Assembly.GetExecutingAssembly() });
Any ideas?
Any time you use a dependency with a Scoped lifetime, you will need to use it inside a pre-created scope. In the case of MVC this would happen automatically behind the scenes but if you're using direct from your own code, say via a console application or something, you will need to create the scope yourself.
This can be done by injecting an instance of IServiceScopeFactory and then using this factory to create a scope and then retrieve the dependency from that scope e.g.
public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
{
private IServiceScopeFactory _serviceScopeFactory;
public MessageCommandHandler(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var myDependency = scopedServices.GetRequiredService<IMyDependency>();
return Task.FromResult(true);
}
}
}
However (and note that the code above is untested), in my own systems I would almost always create the scope around whatever is sending the mediator request in which case any Scoped dependencies will still be injected automatically at this scope e.g.
... // some other calling class / Main method etc..
using (var scope = _serviceScopeFactory.CreateScope())
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
mediator.Send(new MessageCommand());
}

Custom action filter unity dependency injection web api 2

I followed this article and got everything working except dependency inject (partially). In my project I am using unity and I am trying to create a custom Transaction attribute the purpose of which is to start a NHibernate transaction before the execution of an action and commit/rollback the transaction after the method execution.
This is the definition of my attribute:-
public class TransactionAttribute : Attribute
{
}
Following is the definition of my TransactionFilter
public class TransactionFilter : IActionFilter
{
private readonly IUnitOfWork _unitOfWork;
public TransactionFilter(IUnitOfWork uow) {
_unitOfWork = uow;
}
public Task<HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) {
var transAttribute = actionContext.ActionDescriptor.GetCustomAttributes<TransactionAttribute>().SingleOrDefault();
if (transAttribute == null) {
return continuation();
}
var transaction = uow.BeginTransaction();
return continuation().ContinueWith(t =>
{
try{
transaction.Commit();
return t.Result;
}
catch(Exception e)
{
transaction.Rollback();
return new ExceptionResult(ex, actionContext.ControllerContext.Controller as ApiController).ExecuteAsync(cancellationToken).Result;
}
}
}
}
And I have created a custom filter provider which uses unity to construct this filter.
public class UnityActionFilterProvider
: ActionDescriptorFilterProvider,
IFilterProvider
{
private readonly IUnityContainer container;
public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}
public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
foreach (IActionFilter actionFilter in container.ResolveAll<IActionFilter>())
{
// TODO: Determine correct FilterScope
yield return new FilterInfo(actionFilter, FilterScope.Global);
}
}
}
I register the UnityActionFilterProvider in UnityWebApiActivator (I am using Unity.AspNet.WebApi package) as follows
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityDependencyResolver(container);
var config = GlobalConfiguration.Configuration;
config.DependencyResolver = resolver;
var providers = config.Services.GetFilterProviders();
var defaultProvider = providers.Single(i => i is ActionDescriptorFilterProvider);
config.Services.Remove(typeof(IFilterProvider), defaultProvider);
config.Services.Add(typeof(IFilterProvider), new UnityActionFilterProvider(container));
}
The problem is everything works ok for the first request for any action but subsequent requests for the same action doesn't recreate the TransactionFilter which means it doesn't call the constructor to assign a new UOW. I don't think I can disable the action filter caching.
The only option I have got now is to use the service locator pattern and get UOW instance using container inside ExecuteActionFilterAsync which in my opinion kills the purpose of this and I am better off implementing custom ActionFilterAttribute.
Any suggestions ?
As far as I've been able to tell during the years, what happens in web application startup code essentially has Singleton lifetime. That code only runs once.
This means that there's only a single instance of each of your filters. This is good for performance, but doesn't fit your scenario.
The easiest solution to that problem, although a bit of a leaky abstraction, is to inject an Abstract Factory instead of the dependency itself:
public class TransactionFilter : IActionFilter
{
private readonly IFactory<IUnitOfWork> _unitOfWorkFactory;
public TransactionFilter(IFactory<IUnitOfWork> uowFactory) {
_unitOfWorkFactory = uowFactory;
}
// etc...
Then use the factory in the ExecuteActionFilterAsync method:
var transaction = _unitOfWorkFactory.Create().BeginTransaction();
A more elegant solution, in my opinion, would be to use a Decoraptor that Adapts the TransactionFilter, but the above answer is probably easier to understand.

Resolving the same interface with Unity from two different assemblies in a single custom WCF Service Host Factory

I am building a POC that aims to demonstrate how a dependency hierarchy can be constructed from within a WCF service with Unity and keep all assemblies in an application completely loosely coupled.
What I did is to create the following class libraries:
Data Access Layer:
- One assembly with the repository interface.
- One assembly with the implementation of this interface that pretends to access a DB.
- One assembly with the implementation of this interface that pretends to access XML docs.
Business Layer:
- One assembly with the business object interface.
- One assembly with the implementation of this interface that receives on its constructor the repository interface.
Service Layer:
- One assembly with the service interface.
- One assembly with the implementation of this interface that receives on its constructor the business object interface.
Finally I created an assembly with a Service Host Factory, a Service Host, and an Instance Provider that will be in charge of creating the dependency hierarchy. The code looks like so:
public class UnityServiceHostFactory : ServiceHostFactory
{
private readonly UnityContainer _container;
public UnityServiceHostFactory()
{
_container = new UnityContainer();
new ContainerConfigurator().Configure(_container);
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new UnityServiceHost(_container, serviceType, baseAddresses);
}
}
public class ContainerConfigurator
{
public void Configure(UnityContainer container)
{
container.RegisterType<IInvoiceRepository, InvoiceRepository>("dbInvoiceRepository");
container.RegisterType<IInvoiceRepository, XmlInvoice>("xmlInvoiceRepository");
container.RegisterType<IInvoiceFinder, InvoiceFinder>();
}
}
public class UnityServiceHost : ServiceHost
{
public UnityServiceHost(UnityContainer container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if(container == null) throw new ArgumentNullException("container");
var contracts = ImplementedContracts.Values;
foreach (var c in contracts)
{
var instanceProvider = new UnityInstanceProvider(container, serviceType);
c.Behaviors.Add(instanceProvider);
}
}
}
public class UnityInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly UnityContainer _container;
private readonly Type _serviceType;
public UnityInstanceProvider(UnityContainer container, Type serviceType)
{
if (container == null) throw new ArgumentNullException("container");
if (serviceType == null) throw new ArgumentNullException("serviceType");
_container = container;
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
_container.Teardown(instance);
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
}
I am testing this with a console application, I instantiate the service proxy and make the call to its method but, since both registrations are named Unity does not know which one to instantiate. If I remove the name from either of them it gets resolved successfully.
Basically I would like to be able to do something like this:
static void Main(string[] args)
{
//First call, want it to resolve to the InvoiceRepository concrete type
//new InvoiceService(new InvoiceFinder(new InvoiceRepository))
var invoiceService1 = new InvoiceProxy();
var response1 = invoiceService1.GetSumarizedInvoiceBy(new InvoiceRequest(1));
//Second call, want it to resolve to the XmlInvoice concrete type
//new InvoiceService(new InvoiceFinder(new XmlInvoice))
var invoiceService2 = new InvoiceProxy();
var response2 = invoiceService2.GetSumarizedInvoiceBy(new InvoiceRequest(2));
}
Notice how invoiceService1 and invoiceService2 are two different instances of the same service but the dependency within its own dependency was resolved differently for both.
What do I have to do so that I can tell Unity which repository to instantiate when I am either instantiating the service proxy or calling its method?
Thanks for your help.
Pass the name you gave Unity in the RegisterType<>() call to Resolve<>().
From Resolving an Object by Type and Registration Name
// Create container and register types
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType(typeof(MyServiceBase), typeof(DataService), "Data");
myContainer.RegisterType(typeof(MyServiceBase), typeof(LoggingService), "Logging");
// Retrieve an instance of each type
MyServiceBase myDataService = (MyServiceBase)myContainer.Resolve(typeof(MyServiceBase), "Data");
You are using the generic extension methods that are equivalent to this example.

Handling Invalid URI passed to a WCF service

I have WebGet, and WebInvoke attributes describing my contract, but what is the best method of handling invalid URI's? Right now, if a user passes an URI that does not match my current operations, they get an "Endpoint not found." message. I want to pass back a more descriptive message.
For example, my URI template looks like:
/Stuff/{ID}/subStuff
but say they type
/Stuff/{ID}/OtherStuff
There is no such thing as OtherStuff, and I do not have a template for that.
Is there a way to cover all non mapped URI's with a single contract?
Thanks!
If you want to catch all the unhandled requests at a global level in WCF REST then you have to create a custom WebHttpBehavior and custom IOperationInvoker as described in this post.
If you want to return a custom error text with custom status code(404) you can also look into the WebOperationContext.OutgoingResponse property as described here.
While I did follow the links mark provided, and they did give a hint of what I needed. The answers that were linked did not actually answer my original question.
I was able to follow the steps, and I wanted to list my steps to solve this problem on this question as well.
To create my own response to any URI that was not mapped to a method in my contract I created the following:
A custom ServiceHostFactory
Behavior that I mapped to my end points within the custom ServiceHostFactory
a dispatcher that would handle all unmapped uri's that were provided to the service.
Below are the full definitions of the object's I created:
using System.ServiceModel;
using System.ServiceModel.Activation;
namespace your.namespace.here
{
public class CustomServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
//note: these endpoints will not exist yet, if you are relying on the svc system to generate your endpoints for you
// calling host.AddDefaultEndpoints provides you the endpoints you need to add the behavior we need.
var endpoints = host.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new WcfUnkownUriBehavior());
}
return host;
}
}
}
As you can see above, we are adding a new behavior: WcfUnknownUriBehavior. This new custom behavior's soul duty is to replace the UnknownDispatcher. below is that implementation:
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;
namespace your.namespace.here
{
public class UnknownUriDispatcher : IOperationInvoker
{
public object[] AllocateInputs()
{
//no inputs are really going to come in,
//but we want to provide an array anyways
return new object[1];
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
var responeObject = new YourResponseObject()
{
Message = "Invalid Uri",
Code = "Error",
};
Message result = Message.CreateMessage(MessageVersion.None, null, responeObject);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
outputs = new object[1]{responeObject};
return result;
}
public System.IAsyncResult InvokeBegin(object instance, object[] inputs, System.AsyncCallback callback, object state)
{
throw new System.NotImplementedException();
}
public object InvokeEnd(object instance, out object[] outputs, System.IAsyncResult result)
{
throw new System.NotImplementedException();
}
public bool IsSynchronous
{
get { return true; }
}
}
}
Once you have these objects specified, you can now use the new factory within your svc's "markup":
<%# ServiceHost Language="C#" Debug="true" Service="your.service.namespace.here" CodeBehind="myservice.svc.cs"
Factory="your.namespace.here.CustomServiceHostFactory" %>
And that should be it. as long as your object "YourResponseObject" can be serialized, it's serialized representation will be sent back to the client.

MissingTransactionException when running NHibernate with Castle.Facilities.AutoTx

I'm trying to configure Castle Windsor with NHibernate and Castle.Facilities.AutoTx, but I keep getting problems with the PerTransactionLifeStyleOption. If I do
var sessionFactory = Container.Resolve<Func<ISession>>();
var session = sessionFactory();
I get the following exception (on the second line above):
Castle.Facilities.AutoTx.MissingTransactionException:
No transaction in context when trying to instantiate model 'NHibernate.ISession'
for resolve type 'NHibernate.ISession'. If you have verified that your call
stack contains a method with the [Transaction] attribute, then also make sure
that you have registered the AutoTx Facility.
at Castle.Facilities.AutoTx.Lifestyles.PerTransactionLifestyleManagerBase.Resolve(CreationContext context) in d:\Builds\Castle.Transactions-beta\src\Castle.Facilities.AutoTx\Lifestyles\PerTransactionLifestyleManagerBase.cs:line 153
at Castle.Facilities.AutoTx.Lifestyles.WrapperResolveLifestyleManager`1.Resolve(CreationContext context) in d:\Builds\Castle.Transactions-beta\src\Castle.Facilities.AutoTx\Lifestyles\WrapperResolveLifestyleManager.cs:line 143
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired)
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context, Boolean instanceRequired)
at Castle.MicroKernel.Handlers.AbstractHandler.Resolve(CreationContext context)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments)
at Castle.MicroKernel.DefaultKernel.Resolve(Type service, IDictionary arguments)
at Castle.Facilities.TypedFactory.TypedFactoryComponent.Resolve(IKernel kernel)
at Castle.Facilities.TypedFactory.Resolve.Invoke(IInvocation invocation)
at Castle.Facilities.TypedFactory.TypedFactoryInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.Func`1Proxy.Invoke()
at IntegrationTest.NCVIB.WindsorIoC.LocalDbTest.get_Reader() in D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\WindsorIoC\LocalDbTest.cs:line 22
at IntegrationTest.NCVIB.InspectionObjectMapTests.ReadWrite() in D:\Projects\NCVIB-GIT\NCVIB\src\IntegrationTest.NCVIB\InspectionObjectMapTests.cs:line 34
Here's a compilation of the setup calls I'm making (They're actually spread out across several different installers):
container.AddFacility<AutoTxFacility>();
container.Register(Component.For<INHibernateInstaller>().Instance(new FluentNHibernateInstaller));
container.AddFacility<NHibernateFacility>(fac => fac.Option = DefaultSessionLifeStyleOption.SessionPerTransaction);
The FluentNHibernateInstaller is shown here:
public class FluentNHibernateInstaller : INHibernateInstaller
{
public FluentConfiguration BuildFluent()
{
return Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005
.DefaultSchema("dbo")
.ConnectionString(b => b.Is(ConnectionString ?? ConnectionStringChooser.GetConnectionString())))
.Cache(c => c.UseQueryCache().ProviderClass<SysCacheProvider>())
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>().Conventions.AddFromAssemblyOf<EnumConvention>())
.ExposeConfiguration(
c => c.SetProperty(Environment.SqlExceptionConverter, typeof (MsSqlExceptionConverter).AssemblyQualifiedName))
.ExposeConfiguration(c => c.SetProperty(Environment.ShowSql, "true"));
}
public string ConnectionString { get; set; }
public void Registered(ISessionFactory factory)
{
}
public bool IsDefault
{
get { return true; }
}
public string SessionFactoryKey
{
get { return "default.sf"; }
}
public Maybe<IInterceptor> Interceptor
{
get { return Maybe.None<IInterceptor>(); }
}
}
It turns out that that the AutoTxFacility MUST be added to the container before any any component that has a [Transaction] attribute.
I was adding the facility in one of a few IWindsorInstaller classes in which the order of installation was "random" causing the facility to be installed AFTER some of my components with transactional methods:
var container = new WindsorContainer();
container.Install(FromAssembly.This);
But now I am adding the facility BEFORE installing from my installer classes:
var container = new WindsorContainer();
container.AddFacility<AutoTxFacility>();
container.Install(FromAssembly.This());
Here is what the usage would be like:
public class MyClass
{
private readonly Func<ISession> _sessionFactory;
public MyClass(Func<ISession> sessionFactory)
{
_sessionFactory = sessionFactory;
}
[Transaction]
public virtual void UseTheSessionForSomething()
{
// The transaction (and session) will be initialized
// because of the
// [Transaction] attribute
// AND this method is virtual
// AND this instance was resolved from the container
MethodWithinTransactionScope();
}
public void MethodWithinTransactionScope()
{
// Method just needs to be invoked in the scope of a transaction
var session = _sessionFactory();
session.Get<Entity>(1);
}
}
public void Test()
{
var myInstance = container.Resolve<MyClass>();
myInstanace.UseTheSessionForSomething();
}
Is the exception says; the answer is to add a transaction around the method with the line of code: var session = sessionFactory();
If you are getting the exception and HAVE added [Transaction] on that method, then you are not resolving the service LocalDbTest properly.
Have a look at my quick-start for a quick-start:
https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start
I'm reading your code now ;), the reason that it was missing was because of this line:
https://github.com/haf/Castle.Transactions/blob/master/src/Castle.Facilities.AutoTx/AutoTxFacility.cs#L86
It's a known 'TODO' that you have to register your facility before your components, and I think this is stated in the quickstart as well.
Cheers