AutoFac equivalent of this ninject command/function - autofac

In Ninject i can configure a container like the mentioned below, What is the Autofac equivalent for the "Highlighted ones"?
Currently i am trying to achieve the same using AutoFac, any help is much appreciated.
public class NinjectAdapter : IContainerAdapter
{
private readonly IKernel _kernel;
public NinjectAdapter(IKernel kernel)
{
_kernel = kernel;
}
**public void Register(Type service, Type implementation)
{
_kernel.Bind(service).To(implementation);
}**
**public void Register(Type service, Type implementation, Type conditionType)
{
_kernel.Bind(service).To(implementation).WhenInjectedInto(conditionType);
}**
**public void Register(Type service, Type implementation, string named)
{
_kernel.Bind(service).To(implementation).Named(named);
}**
**public void RegisterSingleton(Type service, Type implementation)
{
_kernel.Bind(service).To(implementation).InSingletonScope();
}**
**public void RegisterInScope(Type service, Type implementation)
{
_kernel.Bind(service).To(implementation).InScope(scope => HttpContext.Current);
}**
**public void RegisterInstance(Type service, object instance)
{
_kernel.Bind(service).ToConstant(instance);
}**
**public void RegisterInstance(Type service, object instance, string named)
{
_kernel.Bind(service).ToConstant(instance).Named(named);
}**
}

Related

Add data to the RoutingContext of Vert.x middleware

Say I have this middleware class:
public class Middleware implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
ctx.set("foo", "bar"); // ctx.set is an imaginary method
ctx.next();
}
}
the ctx.set() method is made-up - it doesn't exist on version 3.6.2.
So how can we set arbitrary info on the context of the request?
There is a put method for that:
public class Middleware implements Handler<RoutingContext> {
public void handle(RoutingContext ctx) {
ctx.put("foo", "bar");
ctx.next();
}
}

Passing connection string to Entity framework at runt time for each call

My Entity framework context is as following
public partial class MyContext : DbContext, IMyContext
{
static MyContext()
{
System.Data.Entity.Database.SetInitializer<MyContext>(null);
}
public MyContext()
: base("Name=MyContext")
{
}
I am resolving it through autofac in the following way
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
This db context gets called in repository layer
#region Fields
private readonly IMyContext _context;
#endregion
#region Constructors and Destructors
public EmployeeRepository(IMyContext context)
{
_context = context;
}
#endregion
public void Create(Employee emp)
{
this._context.Employee.Add(emp);
}
Now my issue is , I want to set the connection string dynamically per call. The connection string will be passed through a webapi which i want to pass on to this context. Can anyone help me how can i do that? I am confused about autofac here. Secondly how can i make sure each call sets connection string and does not cache it.
You can use a factory that will build the context and set the connectionstring for you.
public interface IContextFactory
{
IContext GetInstance();
}
public class MyContextFactory : IContextFactory
{
public IContext GetInstance()
{
String connectionString = this.GetConnectionString(HttpContext.Current);
return new MyContext(connectionString);
}
private String GetConnectionString(HttpContext context)
{
// do what you want
}
}
builder.RegisterType<MyContextFactory>()
.As<IContextFactory>()
.InstancePerRequest();
builder.Register(c => c.Resolve<IContextFactory>().GetInstance())
.As<IContext>()
.InstancePerRequest();
If you can't get connectionstring based on HttpContext, you can change contextFactory implementation to expect initialization by WebAPI before creating the instance. For example :
public interface IContextFactory
{
IContext GetInstance();
void Initialize(String connectionString);
}
public class MyContextFactory : IContextFactory
{
private String _connectionString;
public void Initialize(String connectionString)
{
this._connectionString = connectionString;
}
public IContext GetInstance()
{
if (this._connectionString == null)
{
throw new Exception("connectionString not initialized");
}
return new MyContext(this._connectionString);
}
}
At the beginning of your web API call (through attribute for example), you can call the Initialize method. Because the factory is InstancePerRequest you will have one instance for the duration of the request.
By the way, I'm not sure to understand this registration
builder.RegisterType(typeof(MainContext)).As(typeof(DbContext)).InstancePerLifetimeScope();
builder.RegisterType<MainContext>().As<IMainContext>().InstancePerRequest();
It looks buggy because you will have 2 different registration of the same type and not for the same scope, is it intended ? Furthermore, it doesn't sound a good idea to register a DbContext, do you need this registration ?
The following registration looks better :
builder.RegisterType<MainContext>()
.As<IMainContext>()
.As<DbContext>()
.InstancePerRequest();

Injecting a Factory that accepts a Parameter with AutoFac

I've read over several examples that were more complex then I needed and I'm having trouble distilling this down to a simple, concise pattern.
Let's say I have an interface names ICustomService and multiple implementations of ICustomService. I also have a class Consumer that needs to determine at run time which ICustomService to use based upon a parameter.
So I create a classes as follows:
public class Consumer
{
private CustomServiceFactory customServiceFactory;
public Consumer(CustomServiceFactory _customServiceFactory)
{
customServiceFactory = _customServiceFactory;
}
public void Execute(string parameter)
{
ICustomService Service = customServiceFactory.GetService(parameter);
Service.DoSomething();
}
}
public class CustomServiceFactory
{
private IComponentContext context;
public CustomServiceFactory(IComponentContext _context)
{
context = _context;
}
public ICustomService GetService(string p)
{
return context.Resolve<ICustomService>(p); // not correct
}
}
public class ServiceA : ICustomService
{
public void DoSomething()
{
}
}
public class ServiceB : ICustomService
{
public void DoSomething()
{
}
}
Is there an advantage to having my factory implement an interface? How do I fix my factory and register these classes with Autofac so that Consumer.Execute("A") calls DoSomething on WorkerA and Consumer.Execute("B") calls DoSomething on WorkerB?
Thank you
You would register your implementations of ICustomService with keys. For example:
builder.RegisterType<FooService>.Keyed<ICustomService>("someKey");
builder.RegisterType<BarService>.Keyed<ICustomService>("anotherKey");
and then your factory method would be:
public ICustomService GetService(string p)
{
return context.ResolveKeyed<ICustomService>(p);
}
But, you can take this a step further and decouple CustomServiceFactory from IComponentContext:
public class CustomServiceFactory
{
private Func<string, ICustomService> _create;
public CustomServiceFactory(Func<string, ICustomService> create)
{
_create = create;
}
public ICustomService GetService(string p)
{
return _create(p);
}
}
which you would register like so:
builder.Register(c => {
var ctx = c.Resolve<IComponentContext>();
return new CustomServiceFactory(key => ctx.ResolveKeyed<ICustomService>(key));
});
And at that point, assuming CustomServiceFactory doesn't have any other behavior that was omitted for the question, then you as might as well just use and register Func<string, ICustomService> directly.

MvvmCross: IoC with Decorator pattern, two implementations of the same interface

I'd like to implement the Decorator pattern in one of my Mvx projects. That is, I'd like to have two implementations of the same interface: one implementation that is available to all of the calling code, and another implementation that is injected into the first implementation.
public interface IExample
{
void DoStuff();
}
public class DecoratorImplementation : IExample
{
private IExample _innerExample;
public Implementation1(IExample innerExample)
{
_innerExample = innerExample;
}
public void DoStuff()
{
// Do other stuff...
_innerExample.DoStuff();
}
}
public class RegularImplementation : IExample
{
public void DoStuff()
{
// Do some stuff...
}
}
Is it possible to wire up the MvvmCross IoC container to register IExample with a DecoratorImplementation containing a RegularImplementation?
It depends.
If DecoratorImplementation is a Singleton, then you could do something like:
Mvx.RegisterSingleton<IExample>(new DecoratorImplementation(new RegularImplementation()));
Then calls to Mvx.Resolve<IExample>() will return the instance of DecoratorImplementation.
However, if you need a new instance, unfortunately the MvvmCross IoC Container doesn't support that. It would be nice if you could do something like:
Mvx.RegisterType<IExample>(() => new DecoratorImplementation(new RegularImplementation()));
Where you'd pass in a lambda expression to create a new instance, similar to StructureMap's ConstructedBy.
Anyway, you may need to create a Factory class to return an instance.
public interface IExampleFactory
{
IExample CreateExample();
}
public class ExampleFactory : IExampleFactory
{
public IExample CreateExample()
{
return new DecoratorImplementation(new RegularImplementation());
}
}
Mvx.RegisterSingleton<IExampleFactory>(new ExampleFactory());
public class SomeClass
{
private IExample _example;
public SomeClass(IExampleFactory factory)
{
_example = factory.CreateExample();
}
}

autofac baseclass property is null

Here is my setup with Asp.Net Mvc 3:
public abstract class BaseProvider
{
protected ICache Cache;
}
public interface ICache
{
void Add(string key, object data);
void Remove(string key);
...
}
public class MyCache : ICache
{
private static MemoryCache cache = MemoryCache.Default;
void Add(string key, object data)
{
...
}
}
public interface IEmployeeProvider
{
IEnumerable<Employee> GetEmployees(string department);
}
public class EmployeeProvider:BaseProvider,IEmployeeProvider
{
public IEnumerable<Employee> GetEmployees(string department)
{
**if (Cache.Get("employees_"+department)!=null)**
}
}
Starred line throws an error saying that Cache is null.
I tried to register the base class as a type but, I guess it is wrong.
My Autofac setup is like this:
builder.Register(r => new EmployeeProvider()).As<IEmployeeProvider>().InstancePerHttpRequest();
builder.Register(r => new MyCache()).As<ICache>().InstancePerHttpRequest();
builder.RegisterType<BaseProvider>().PropertiesAutowired();
What am I missing?
You should either register EmployeeProvider with PropertiesAutowired() or scan the assembly for every class that inherits from BaseProvider.
The first registration forgets the PropertiesAutowired(), the third line forgets the EmployeeProvider.