Automapper global destination instantiator - c#

I am using automapper to map my DTOs to Viewmodels, some of my viewmodels have a dependency to a service.
I found a couple of ways to construct the destination object using these dependencies but i wonder if it is possible to just use a global object resolver (UnityContainer in my case)?
my current solution is this:
config.CreateMap<SurveyDTO, SurveyViewModel>()
.ConstructUsing(x => _ObjectResovler.Resolve<SurveyViewModel>())
or alternatively
config.CreateMap<SurveyDTO, SurveyViewModel>()
.ConstructUsingServiceLocator()
But this means that i have to include a line like this in every mapping.
Is there a way to just use the resolver for all mappings without specifying it in the configuration?

I solved it by using
config.ForAllMaps((map, opts) => opts
.ConstructUsing(x => _ObjectResovler.Resolve(map.DestinationType)));
for the servicelocator alternative you could use:
config.ForAllMaps((map, opts) => opts.ConstructUsingServiceLocator());

Related

Custom Value Resolver in Mapster

I've been working with AutoMapper and it was quite joyful but for a number of reasons I got to use Mapster in my new project.
As you may know we had a handy configuration for CustomValueResolvers:
CreateMap<Context.Models.Employee, EmployeeDTO>()
.ForMember(dest => dest.CustomValue, opt => opt.MapFrom<EmployeeCustomValueResolver>());
EmployeeCustomValueResolver was a class with its own template you could inject DbContext and read whatever you need and return whatever you want:
public class EmployeeCustomValueResolver: IValueResolver<Context.Models.Employee, EmployeeDTO, List<anyType>>
{
//Read whatever you want from db and return.
}
But now in this Mapster I don't know how to do that.
I have a type config section like this:
TypeAdapterConfig<Employee, EmployeeDTO>.NewConfig()
.Map(dest=>dest.Gates,src=>src.Gates.ToList())
but this is not what I want. I want to create a custom class as a custom value resolver and return my Gates as a result and I don't know how? I need something like AutoMapper ValueResolver.
Any help is appreciated.

Registering an assembly is also registering enums

I am using DRYIOC for DI in my application. I have interfaces in my MVC application which I want to register to dryIOC. So I am using RegisterMany as below.
container.RegisterMany(new[] { Assembly.Load(DIAssemblyCollection["WebAssembly"]) },
serviceTypeCondition: type => type.IsInterface,
setup: Setup.With(allowDisposableTransient: true));
But I am getting the error as below
Unspecified how to select single constructor for implementation type Web.Enums.Enum1 with 0 public constructors.
Seems like a bug, but need to look at code first.
Meanwhile you can just filter implementation types, keep classes only:
container.RegisterMany(
Assembly.Load(DIAssemblyCollection["WebAssembly"])
.GetLoadedTypes()
.Where(type => type.IsClass),
serviceTypeCondition: type => type.IsInterface,
setup: Setup.With(allowDisposableTransient: true));
Live example
Update
Fixed in DryIoc 2.7

Register same implementation for multiple interfaces

I have a class that implements a number of interfaces
public class AwesomeThingClass: IAwesome<Thing>, IAwesomeThing {
// parameterized constructor, so can't use RegisterAutowiredAs
public AwesomeThingClass(IClient client, string connectionString) {}
}
It encapsulates multithreading operations with limited cardinality (I mean, only N of such operations are allowed to run simultaneously) by using semaphores.
However, if I register it with IoC using something like
container.Register<IAwesome<Thing>>(cont => new AwesomeThingClass(cont.Resolve<IClient>(), connStr))
container.Register<IAwesomeThing>(cont => new AwesomeThingClass(cont.Resolve<IClient>(), connStr))
I end up with two instances that could be resolved using IAwesome<Thing> and IAwesomeThing, which allows to run 2*N operations. I definitely need same instance resolved for both interfaces. Are there any way to achieve this, except for manually instantiating class and registering instance?
This question is essentially similar to Register the same type to multiple interfaces, but it's not it's duplicate, as I'm using ServiceStack IoC container (Func at the time of writing), while that question is about Unity
There might be a simple solution specialized for ServiceStack IoC but you could also use a Lazy<T> to return the same value from both of your lambdas.
var lazy = new Lazy<AwesomeThingClass>(() =>
new AwesomeThingClass(container.Resolve<IClient>(), connStr));
container.Register<IAwesome<Thing>>(cont => lazy.Value);
container.Register<IAwesomeThing>(cont => lazy.Value);
(I'm assuming that the cont parameter of the lambda would be the same object as the container variable.)
You should be able to just cast it:
container.Register<IAwesomeThing>(c =>
new AwesomeThingClass(c.Resolve<IClient>(), connStr));
container.Register(c => (IAwesome<Thing>) c.Resolve<IAwesomeThing>()));

Ninject Convention Based Configuration

Is it possible to configure Ninject so that it automatically binds a type of interface to a concrete type based on the class naming conventions? I'm using Ninject version 3.
For example I have a lot of repositories in my domain layer named ITypeRepository which are implemented in my infrastructure layer as ProviderTypeRepository.
Below is an example of how I'm currently binding these is Ninject's CreateKernal method.
kernel.Bind<IClientRepository>().To<ProviderClientRepository>();
kernel.Bind<IVacancyRepository>().To<ProviderVacancyRepository>();
kernel.Bind<ICandidateRepository>().To<ProviderCandidateRepository>();
...etc etc
What I'd like is to somehow map this in one pass so that whenever I add a new repository I don't need to manually bind it.
You're looking for the Ninject Conventions Extension which can do something like:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses().EndingWith("MySuffix")
.BindAllInterfaces();

StructureMap with my own attributes in C#

I have an attribute that I have written that has a dependency on the Data Access Layer so I made a constructor that took the DAL class as a parameter (marked with [DefaultConstructor] and another, blank, constructor that is parameterless. When I call a method that depends on the attribute how do I make StructureMap inject the correct type?
Thanks
Gareth
I have been working on the same problem, i'm using something like this:
ObjectFactory.Initialize(x =>
{
x.PullConfigurationFromAppConfig = true;
x.SetAllProperties(p => p.TypeMatches(t =>
t.GetCustomAttributes(typeof(InjectAttribute), true).Length > 0));
}
I am having some issues injecting onto webform pages but it works when creating instances using ObjectFactory...

Categories

Resources