In my CLI Main I need a object of my MonDbBusinessComponent class.
I wrote the code below, but my object is still null.
What's wrong? How to do it right?
public static IMonDbBusinessComponent monDbBusinessComponent { get; set; }
static void Main(string[] args)
{
var collection = new ServiceCollection();
collection.AddScoped<IMonDbRepository, MonDbRepository>();
ServiceProvider appServiceProvider = GetServiceProvider();
monDbBusinessComponent = appServiceProvider.GetService<IMonDbBusinessComponent>();
you never registered your IMonDbBusinessComponent.
collection.AddScoped<IMonDbBusinessComponent, MonDbBusinessComponent>();
I'm sorry, it was not possible to see in my published coded. The BusinessComponent uses Repository and first I needed to register the Repository with it's arguments and then register the BusinessComponent.
Also at the BusinessComonent I needed to use the Interface instead of the class.
public MonDbBusinessComponent(IMonDbRepository monDbRepository){...}
collection.AddScoped<IMonDbRepository>(ServiceProvider =>
{
string createMetaDataRecordFunctionName = Configurations.Get(LocalConfiguration, "CreateMetaDataRecordFunctionName");
string conDbDataRecordFunctionName = Configurations.Get(LocalConfiguration, "ConDbDataRecordFunctionName");
return new MonDbRepository(metaDataConnection, createMetaDataRecordFunctionName, conDbDataRecordFunctionName);
});
collection.AddScoped<IMonDbBusinessComponent, MonDbBusinessComponent>();
Thanks for all support!
Related
I am using:
Microsoft.Extensions.DependencyInjection version 5.0.1 nuget package, and I am creating a class called ArrowGrid that creates some graphic elements.
I would like to call the class like this in C# and possibly XAML:
var arrowGrid = new ArrowGrid();
<ArrowGrid />
However ArrowGrid needs a service:
public class ArrowGrid : BaseGrid
{
private readonly IGraphicsService _graphicsService;
public ArrowGrid(IGraphicsService graphicsService)
{
_graphicsService = graphicsService;
var fr = _graphicsService.GetFrameWithArrow();
Children.Add(fr, 3, 0);
}
}
Now I have a problem as new ArrowGrid() will give me an error saying there is no default constructor with no arguments so I had an idea to do this:
public class ArrowGrid : BaseGrid
{
private readonly IGraphicsService _graphicsService;
public ArrowGrid()
{
_graphicsService = Startup.ServiceProvider.GetRequiredService<GraphicsService>();
var fr = _graphicsService.GetFrameWithArrow();
Children.Add(fr, 3, 0);
}
}
But from what I read see below it's always suggested to use constructor arguments:
Of course, you typically shouldn't be using the IServiceProvider
directly in your code at all. Instead, you should be using standard
constructor injection, and letting the framework worry about using
IServiceProvider behind the scenes.
Is it just with the Microsoft.Extensions.DependencyInjection that this is a problem? How about with other DI solutions? I don't know about those and would appreciate advice as to if they offer more capabilities. Also is my idea the correct way to overcome this problem? Note that in this case the graphicsService is a very simple service that I would never need to replace when doing testing.
Here's what I am currently doing:
var abc = new ArrowGrid
{
Text1 = "Talk to us",
TapCommandParam = "Home/FBPage",
IconSource = Const.IconSource.CardOptions,
};
Here I believe is the suggestion:
var abc = Startup.ServiceProvider.GetRequiredService<ArrowGrid>();
abc.Text1 = "Talk to us";
abc.TapCommandParam = "Home/FBPage";
abc.IconSource = Const.IconSource.CardOptions;
Startup.ServiceProvider.GetRequiredService<ArrowGrid>() looks fine for me but there's a better way to do that. DI Container allows you to be lazy and not create anything yourself either with new, or with DI Container imperatively.
Consider this example. Hope the class where you writing the code is registered in the ServiceCollection.
public class MyTestClass
{
public MyTestClass()
{
var abc = Startup.ServiceProvider.GetRequiredService<ArrowGrid>();
abc.Text1 = "Talk to us";
abc.TapCommandParam = "Home/FBPage";
abc.IconSource = Const.IconSource.CardOptions;
}
}
Can be easily replaced with DI version of the same.
public class MyTestClass
{
public MyTestClass(ArrowGrid abc)
{
abc.Text1 = "Talk to us";
abc.TapCommandParam = "Home/FBPage";
abc.IconSource = Const.IconSource.CardOptions;
}
}
That's the sense of Composition Root of your App where the classes are registered.
I am facing a little problem related to dependency injection. I have a program, using respectfully state of the art rules of dependency injection, used from example of an ASP.NET MVC project, and some console programs.
But it also contains some kind of "service locator" anti pattern.
I'll attempt to illustrate it with a very simple console project :
using System;
using Autofac;
using System.Collections.Generic;
using System.Linq;
namespace AutofacIssue
{
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterModule<MyModule>();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var service = scope.Resolve<UserService>();
var users = service.CreateSomeUsers();
var info = users.First().GetSomeInfo;
Console.WriteLine(info.Something);
}
}
}
internal class MyModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<UserService>();
builder.RegisterType<UserRelatedInfoService>();
}
}
internal class UserRelatedInfoService
{
public UserInfo GetForUser(int id)
{
return new UserInfo("Various infos for " + id);
}
}
internal class UserService
{
public IEnumerable<User> CreateSomeUsers()
{
return Enumerable.Range(1, 10).Select(r => new User(r)); // Remark "new User()" is called from many various spaces !
}
}
internal class UserInfo
{
// Some things
public string Something;
public UserInfo(string someThings)
{
this.Something = someThings;
}
}
/// <summary>
/// "Service locator" antipattern
/// </summary>
class DependencyLocator
{
public static IContainer Container { get; }
static DependencyLocator()
{
var builder = new ContainerBuilder();
builder.RegisterModule<MyModule>();
Container = builder.Build();
}
}
internal class User
{
public User(int id)
{
this.Id = id;
}
public int Id { get; private set; }
/// <summary>
/// Here's my problematic property using the DependencyLocator
/// </summary>
public UserInfo GetSomeInfo
{
get
{
UserRelatedInfoService userRelatedInfoService = DependencyLocator.Container.Resolve<UserRelatedInfoService>();
return userRelatedInfoService.GetForUser(Id);
}
}
}
}
The anti pattern allows to write very small code working perfectly well, but violating some of the principles of DI (due to "service locator" + duplicated Container, having each their own lifetime).
This implementation also have the advantage to instantiate UserRelatedInfoService only when it's actually needed, if the related property of User is actually called (please keep in mind the real world example is much more complicated and some of the operations related to this may have a cost)
In the real world example, I have this situation in many assemblies, each of them needing to be able to resolve dependencies by the same way.
My question is: without to modify the User constructor, and the constructors of all objects instantiating some User, is there a clean way to avoid this?
By some kind of "dynamic resolving" of dependencies for example?
Please note that User is not in the same assembly as my Program class, so I can't access the original Container as a public property.
One solution I thought was to keep the class DependencyLocator but to remove its content, and just assign its Container property with the one created in main.
edit : FYI, so far I just followed my own suggestion and modified DependencyLocator to avoid it to rebuild its own container, and just set on it the final container built at entry point of application. It was an easy change to do and it avoids most of the problems pointed in original question.
At least, the code will always use the same container.
Thanks for reading!
For edge cases like this where you need runtime resolution by type, you can register IServiceProvider or a Func (Or a Func with the object[] being input parameters)
builder.Register(ctx => ctx as IServiceProvider ??
ctx.Resolve<ILifetimeScope>() as IServiceProvider)
.InstancePerLifetimeScope().AsSelf();
or
builder.Register(c =>
{
var scope = c.Resolve<ILifetimeScope>();
return (Func<Type, object>)(t => scope.Resolve(t));
}).As<Func<Type, object>>();
I am trying to implement some syntactic sugar around the registration of multiple things with Autofac but I'm stuck and I don't know whether this has some design pattern name where I could search some information for.
I have something like this in my main project:
protected override void Load(ContainerBuilder builder)
{
var busBuilder =
new BusBuilder()
.RegisterHandler<EventOne, DomainEventHandlerAdapter<EventOne>>()
.RegisterHandler<EventTwo, DomainEventHandlerAdapter<EventTwo>>()
.RegisterHandler<EventThree, DomainEventHandlerAdapter<EventThree>>();
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
I want to refactor this, because I don't want my main project to have a dependency to that specific NuGet package (the Enexure Microbus package). So I would like to have in my main project something like this:
protected override void Load(ContainerBuilder builder)
{
builder.RegisterMyMicrobus(eventOptions => {
eventOptions
.RegisterDomainHandler<EventOne>()
.RegisterDomainHandler<EventTwo>()
.RegisterDomainHandler<EventThree>();
});
}
so that my main project knows nothing about BusBuilder, DomainEventHandlerAdapter or RegisterMicroBus and has no dependency on that specific technology (Enexure Microbus). All the Autofac registration would be handled by my other project that is the only one with a dependency to the specific technology.
Here is what I have done so far on my other project:
I have created an extension method on Autofac's ContainerBuilder where I will pass the eventOptions, which would be a delegate (lambda expression) Action<EventOption>
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
if (eventOptions != null)
{
// TODO, how to implement EventOption and the chain registration?
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
Any link or help would be greatly appreciated. This pattern must have a name, but no idea how is it called and I don't have experience implementing chain methods.
UPDATE 1: Following the advice of Erndob I had a look at BusBuilder. But again I reached a point where I am stuck.
I have created EventOption as follows:
public class EventOption
{
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
private readonly List<IDomainEvent> _domainEvents= new List<IDomainEvent>();
public EventOption RegisterDomainHandler(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
return this;
}
}
but now the problem is with the extension method, because I can retrieve the list of events
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
// use busBuilder to register each one of the domain events in options
var eventOption = new EventOption();
eventOptions?.Invoke(eventOption);
foreach (var domainEvent in eventOption.DomainEvents)
{
var eventType = domainEvent.GetType();
// HERE is the problem. How to RegisterHandler using this generic method?
busBuilder
.RegisterHandler<eventType, DomainEventHandlerAdapter<eventType>>();
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
It won't compile because I am trying to use a variable as a Type (RegisterHandler is a generic). I can't find a way to convert my variable into a type to satisfy that call. Any idea or a different way to achieve the same? Thanks again
UPDATE 2: I have changed the approach and it seems it could work. It compiles and it registers everything, but I have to test further.
I have modified EventOption to store Types:
public class EventOption
{
public IReadOnlyList<Type> Types => _types.AsReadOnly();
private readonly List<Type> _types = new List<Type>();
public DomainCommandOptions RegisterCommandHandler<TDomainCommand>()
where TDomainCommand : IDomainCommand
{
var domainCommandType = typeof(TDomainCommand);
_types.Add(domainCommandType);
return this;
}
}
and then the extension method is now different, because it iterates over the types and at runtime it creates a generic type. I discovered there is a HandlerRegistration from Microbus I can use directly.
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
// use busBuilder to register each one of the domain events in options
var eventOption = new EventOption();
eventOptions?.Invoke(eventOption);
foreach (var type in eventOption.Types)
{
var handlerRegistration = new HandlerRegistration(type, typeof(DomainEventHandlerAdapter<>).MakeGenericType(type));
busBuilder.RegisterMessage(handlerRegistration);
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
Have a look at the source code of the project you are using. The BusBuilder, the thing that chains, has a pattern name in it's name. A builder. The repo itself says:
MicroBus is a simple in process mediator for .NET
So MicroBus is a Mediator. Have a look at a mediator pattern.
Here's how the BusBuilder.cs looks: https://github.com/Lavinski/Enexure.MicroBus/blob/master/src/Enexure.MicroBus/BusBuilder.cs
The building itself is essentially done like this:
public BusBuilder RegisterHandler<TMessage, TMessageHandler>()
where TMessageHandler : IMessageHandler<TMessage, Unit>
{
registrations.Add(HandlerRegistration.New<TMessage, TMessageHandler>());
return this;
}
As you can see, the instance has a list of registrations, then when you want to register something new, it just adds to the list and then returns itself, letting you to chain a new registration.
I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:
public class NinjectMockProvider<T> : IProvider
{
public static Type Type { get { return typeof(T); } }
public object Create(IContext context)
{
Mock<T> newMock = new Mock<T>();
return newMock.Object;
}
}
But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:
kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();
or something to that effect.
Update
I did figure out that I could accomplish what I want by using Ninject's method binding:
kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);
I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.
Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.
My solution to this always just uses the following:
MoqProvider
public class MoqProvider<T> : Provider<T> // T is the desired service
{
protected override T CreateInstance(IContext context)
{
return new Mock<T>().Object;
}
}
I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.
MoqMissingBindingResolver
public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
{
if (request.Service.IsAbstract || request.Service.IsInterface)
{
var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
return new IBinding[]
{
new Binding(request.Service, new BindingConfiguration
{
ProviderCallback = ctx => moqProvider,
ScopeCallback = Settings.DefaultScopeCallback
})
};
}
else
{
return Enumerable.Empty<IBinding>();
}
}
}
I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:
INinjectSettings Settings = new NinjectSettings
{
DefaultScopeCallback = StandardScopeCallbacks.Singleton
};
var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();
Hope this is helpful.
Is it possible to use automapper in a console application?
Its Getting Started Page suggests the bootstrapper class be called from Application start up, but there are no further details about a class to add and call from Main().
How do I go about using this in a simple console app?
You can initialize Automapper in the console startup, there's no limitations; the Application_start is the startup place for a web program in .net/iis, ie code that is called only once. Any configuration that you must call at the start of a web project goes in this method.
edit for comment: if you don't want to create your mappings on the fly, but would rather have a place to initialize all your mappings, just create a function called InitializeAutomapper and make the Mapper.Configure<X, Y> calls in here. Then in your Main() method, just call the function. There are lots of ways to handle configuration, but this is the simpler way to handle it.
code sample
class Program
{
static void Main(string[] args)
{
// the app is starting here
InitializeAutomapper();
// we're configured, let's go!
DoStuff();
}
static void InitializeAutomapper()
{
AutoMapper.Mapper.CreateMap<TypeA, TypeB>();
AutoMapper.Mapper.CreateMap<TypeC, TypeD>();
AutoMapper.Mapper.CreateMap<TypeE, TypeF>();
}
}
I know that this is an old question, but if you found this I want to add an update: Automaper does not allow static initialization anymore.
You can check more here
Below, I'm providing a full example of how to use it on a console app. Hope this might be helpful for someone in the future.
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<MyClass, MyClassDTO>();
});
IMapper mapper = config.CreateMapper();
var myClass = new MyClass(){
Id = 10,
Name = "Test"
};
var dst = mapper.Map<MyClass, MyClassDTO>(myClass);
Console.WriteLine(dst.Id);
}
}
class MyClass
{
public int Id {get;set;}
public string Name {get;set;}
}
public class MyClassDTO
{
public int Id {get;set;}
public string Name {get;set;}
}
Do not forget to include using AutoMapper;
Yes, but it appears to have a dependency on System.Web, which must be included too.
(See Mysterious disappearing reference for more details)