One can use a value, type or factory for registering an object. I have tried to find simple examples how and when to use each of a registering types, but not succeed.
It would be wonderful, if someone could give brief examples and explain the typical use cases.
Here are some links about the subject:
https://stackoverflow.com/a/21245335/2777805
http://victorsavkin.com/post/72452331552/angulardart-for-angularjs-developers-introduction-to
type
// old syntax
type(SomeType); // or
type(SomeInterface, implementedBy: SomType)
// new syntax
bind(SomeType); // or
bind(SomeInterface, toImplementation: SomType)
default, DI creates an instance and all constructor parameters (if any are resolved by DI and provided)
value
// created inline or e.g. passed in from somewhere as a parameter
// old syntax
value(new SomeType('xxx', 123));
// new syntax
bind(SomeType, toValue: new SomeType('xxx', 123));
if you want to to pass a previously instantiated instance.
I usually use this for configuration settings.
factory
// old syntax
factory(NgRoutingUsePushState,
(_) => new NgRoutingUsePushState.value(false));
// or
factory(UsersRepository, (Injector inj) => new UsersRepository(inj.get(Http)));
// new syntax
bind(NgRoutingUsePushState,toFactory:
(_) => new NgRoutingUsePushState.value(false));
bind(UsersRepository, toFactory: (Injector inj) => new UsersRepository(inj.get(Http)));
(from http://victorsavkin.com/post/72452331552/angulardart-for-angularjs-developers-introduction-to)
when you want DI to delegate the instantiation to a factory function
Related
My use case is in constructing a WidgetApp in flutter:
new WidgetsApp(
pageRouteBuilder: <Contructor for MaterialPageRoute here>,
...
);
Instead of referencing the constructor, I'm just wrapping it in a function:
PageRoute pageRouteBuilder(RouteSettings settings, WidgetBuilder builder) {
return MaterialPageRoute(settings: settings, builder: builder);
}
And then referencing that function later:
new WidgetsApp(
pageRouteBuilder: pageRoutebuilder,
...
);
It used to be possible at some point in the history of Dart (like spread operator).
It is currently not possible though, but the feature may come back at some point.
In the meantime, you can use refactoring options for them to generate some of the boilerplate.
Constructor tear-off are not supported in Dart (https://github.com/dart-lang/sdk/issues/10659)
But even if it was supported, your code cannot really use it. MaterialPageRoute takes settings and builder as named parameters but PageRouteFactory takes 2 positionals parameters. So it wouldn't match.
You can write it like:
new WidgetsApp(
pageRouteBuilder: (settings, builder) => MaterialPageRoute(settings: settings, builder: builder),
);
The automatic inference, allows you to omit the type in the parameter of the closure.
I'm trying to avoid referencing the concrete type library in my main project, but I'm getting this error:
No default instance or named instance 'Default' for requested plugin type StackExchangeChatInterfaces.IClient
1.) Container.GetInstance(StackExchangeChatInterfaces.IClient ,{username=; password=; defaultRoomUrl=; System.Action`2[System.Object,System.Object]=System.Action`2[System.Object,System.Object]})
I've setup my container to scan for assemblies, like so:
var container = new Container(x =>
{
x.Scan(scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.ExcludeNamespace("StructureMap");
scan.WithDefaultConventions();
scan.AddAllTypesOf<IMessageHandlers>();
});
//x.For<IClient>().Use<Client>(); //GetInstance will work if this line is not commented out.
});
When I try to get an instance, I get the error, my code for getting an instance is here:
chatInterface = container
.With("username").EqualTo(username)
.With("password").EqualTo(password)
.With("defaultRoomUrl").EqualTo(roomUrl)
.With<Action<object, object>>(delegate(object sender, object messageWrapper)
{
string message = ((dynamic)messageWrapper).Message;
Console.WriteLine("");
Console.WriteLine(message);
foreach (var item in messageHandlers)
{
item.MessageHandler.Invoke(message, chatInterface);
}
}).GetInstance<IClient>();
If I explicitly map the concrete class to the interface, everything works hunky dory, but that means I need to reference the project that Client is in, which I don't want to do.
This is really interesting. Looks like default conventions are not able to register types with such constructor (tried on both versions 2.6.3 and 3+). I was only registered when only parameterless constructor was specified. Looking at sources of both versions it is really suspicious as it should be registered. Deeper dive into the code would be needed...
Anyway try using custom registration convention:
public class ClientConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.IsClass && !type.IsAbstract && !type.IsGenericType &&
type.GetInterfaces().Contains(typeof(IClient)))
{
registry.For(typeof(IClient)).Use(type);
}
}
}
Configure it like this:
var container = new Container(
c => c.Scan(
s =>
{
s.ExcludeNamespace("StructureMap");
s.WithDefaultConventions();
s.Convention<ClientConvention>();
s.AddAllTypesOf<IMessageHandlers>();
}));
and this should work just fine.
The default type scanning will not pick up concrete types whose constructor functions contain primitive arguments like strings, numbers, or dates. The thinking is that you'd effectively have to explicitly configure those inline dependencies anyway.
"but that means I need to reference the project that Client is in, which I don't want to do."
Does that actually matter? I think you're making things harder than they have to be by trying to eliminate the assembly reference.
I'm using VB.NET MVC 5 with Identity 2.0.
I've been trying to configure my Startup.Auth to automatically use a single instance of ApplicationDbContext, CustomUserManager and CustomRoleManager per request as detailed in this tutorial.
My code is as follows: (minus garbage)
Public Sub ConfigureAuth(app As IAppBuilder)
app.CreatePerOwinContext(ApplicationDbContext.Create)
' Error 135 Overload resolution failed because no accessible 'CreatePerOwinContext' can be called with these arguments:
' Extension method 'Public Function CreatePerOwinContext(Of T)(createCallback As System.Func(Of Microsoft.AspNet.Identity.Owin.IdentityFactoryOptions(Of T), Microsoft.Owin.IOwinContext, T)) As Owin.IAppBuilder' defined in 'Owin.AppBuilderExtensions': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
' Extension method 'Public Function CreatePerOwinContext(Of T)(createCallback As System.Func(Of T)) As Owin.IAppBuilder' defined in 'Owin.AppBuilderExtensions': Data type(s) of the type parameter(s) cannot be inferred from these arguments. Specifying the data type(s) explicitly might correct this error.
app.CreatePerOwinContext(Of CustomUserManager)(CustomUserManager.Create)
' Error 136 Overload resolution failed because no accessible 'Create' accepts this number of arguments.
....
End Sub
But recieve these errors no matter what I do
Overload resolution failed because no accessible 'Create' accepts this number of arguments.
I think it's to do with me writing in VB and the example being in C#, though it infuriates me that this is a problem. My CustomUserManager is a Public Class, and the Create method is Public Shared.
Public Shared Function Create(options As IdentityFactoryOptions(Of CustomUserManager), context As IOwinContext) As CustomUserManager
Dim manager As CustomUserManager
manager = New CustomUserManager(New CustomUserStore(context.Get(Of ApplicationDbContext)()))
manager.UserValidator = New UserValidator(Of ApplicationUser, Integer)(manager)
manager.PasswordValidator = New PasswordValidator() With {
.RequiredLength = 6
}
manager.RegisterTwoFactorProvider("EmailCode",
New EmailTokenProvider(Of ApplicationUser, Integer)() With {
.Subject = "Security Code",
.BodyFormat = "Your security code is: {0}"
}
)
manager.EmailService = New EmailService()
manager.SmsService = New SmsService()
If Not options.DataProtectionProvider Is Nothing Then
manager.UserTokenProvider = New DataProtectorTokenProvider(Of ApplicationUser, Integer)(options.DataProtectionProvider.Create("ASP.NET Identity"))
End If
Return manager
End Function
Any ideas anyone? Any help is much appreciated, Cheers.
Try this
Public Sub ConfigureAuth(app As IAppBuilder)
app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
End Sub
The AddressOf operator creates a function delegate that points to the function specified by procedurename
link1
link2
If you have already updated your visual studio 2013 with Update 3. This comes with all the identity stuff and custom user manager, role manager and many more.
Create new project using MVC template and Authentication selected as Individual User Accounts using Visual Studio 2013. Then you will get created all the code same as you have already implemented using the example. You can use that classes and implementation in order to fix your issues with your custom user manager.
Check the floder App_Start >> IdentityConfig.vb
Only thing I can see in your code, you have used integer as Id rather than string. That won't be a problem if you have correctly bind EF model biding stuff.
I'm attempting to implement Dependency Injection into my architecture (MVC, DDD - Domain Model, Repository). And my architecture includes ASP.NET Identity 2.0.
At this stage, I don't want DI controlling any of the Identity 2.0 objects (UserAdminController, RolesAdminController...). I'd prefer the security objects outside of DI. At this stage, integrating the Identity objects in DI looks very difficult. I had a good look to see if someone has already done this, so I could read and learn how to do this. I couldn't find anything. (Found one post which came close, but no resolution).
Anyway, I've followed the Simple Injector MVC implementation (see standard code below), and trying many things, I believe the problem lies in me calling RegisterMvcControllers.
Correct me if I'm wrong, but this statement will pickup all controllers with their name post-fixed with "controller".
Question: How can I select which controllers get registered with Simple Injector? (Is this called manually registering?)
Any help would be greatly appreciated, as I've spent most of today trying to get my head around all this, and proceed to the next step, i.e. have DI implemented, and instantiating my objects.
...
...
... called from Application_Start()
// Create a Simple Injector container
var container = new Container();
// Configure the container
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
// Verify the container's configuration
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
private static void InitializeContainer(Container container)
{
container.Register<MyService1>();
container.Register<IMyRepositoryA, MyRepositoryA>();
// Trying to include Identity into Simple Injector - please ignore
container.Register<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>(new ApplicationDbContext()));
}
The RegisterMvcControllers has the following constraints on the types it registers:
The type must be public
The type must implement System.Web.Mvc.IController
The type must not be abstract
The type must not be a generic type definition
Its name must end with "Controller"
You can see what happens here in the source code.
The RegisterMvcControllers extension method calls into the SimpleInjectorMvcExtensions.GetControllerTypesToRegister method to get the list of controllers to register. You can call that method yourself to see what is registered as follows:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
So instead of calling RegisterMvcControllers you can register the controllers yourself by calling the GetControllerTypesToRegister method:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly());
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
This way you can filter out any controller you want to register manually:
var registeredControllerTypes =
SimpleInjectorMvcExtensions.GetControllerTypesToRegister(
container, Assembly.GetExecutingAssembly())
.Where(type => type.Name != "UserStore`1");
foreach (var controllerType in registeredControllerTypes)
{
container.Register(controllerType, controllerType, Lifestyle.Transient);
}
Another option is to override the registration:
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Options.AllowOverridingRegistrations = true;
container.Register<IUserStore<ApplicationUser>>(
() => new UserStore<ApplicationUser>(new ApplicationDbContext()))
// Always set the option back to false ASAP to prevent configuration errors.
container.Options.AllowOverridingRegistrations = false;
I'm using StructureMap, v. 2.5.3 and am having trouble with chaining together implementations on an interface to implement the Decorator pattern.
I'm used to Windsor, where it is possible to name variations on interface implementations and send the named impl. into another (default) impl.
This is the default, non decorated version, which works fine:
ObjectFactory.Initialize(registry =>
{
registry.ForRequestedType<ICommentService()
.TheDefault.Is.OfConcreteType<CommentService>();
... }
This is the ctor on the decorator, that I want to call:
public CommentAuditService( ICommentService commentService,
IAuditService auditService )
This works, but does not give me access to the decorated object:
registry.ForRequestedType<ICommentService>()
.TheDefault.Is.OfConcreteType<CommentService>()
.EnrichWith(x => new CommentAuditService());
This takes me int an inf. loop:
registry.ForRequestedType<ICommentService>()
.TheDefault.Is.OfConcreteType<CommentService>()
.EnrichWith(x => new CommentAuditService( new CommentService(),
new AuditService()));
So far this is what seems to me should work:
registry.ForRequestedType<ICommentService.()
.TheDefault.Is.OfConcreteType<CommentAuditService>()
.WithCtorArg("commentService")
.EqualTo(new CommentService());
However it send it into an endless loop of creating new instances of CommentAuditService
Does anyone have an quick answer? (other than switching to Castle.Windsor, which I'm very close to at the moment)
You were very close. Try:
registry.ForRequestedType<ICommentService>()
.TheDefaultIsConcreteType<CommentService>()
.EnrichWith(original => new CommentAuditService(original,
new AuditService()));
If AuditService might itself have dependencies, you would do:
registry.ForRequestedType<ICommentService>()
.TheDefaultIsConcreteType<CommentService>()
.EnrichWith((ioc, original) => new CommentAuditService(original,
ioc.GetInstance<AuditService>()));
Or, if you change the last part to:
ioc.GetInstance<IAuditService>()
you can register the concrete type of your audit service separately.