How can I get this working using only NHibernate 4.0 and CoC?
I need to map two different classes that share the same name:
namespace MyApp.VersionA {
public class User{
//omitted properties
}
}
namespace MyApp.VersionB {
public class User{
//omitted properties
}
}
This is my NHibernate setup method:
var config = new Configuration();
config.Configure();
var mapper = new ModelMapper();
mapper.AddMappings(GetAllMappingTypes());
config.AddMapping(mapper.CompileMappingForAllExplicitlyAddedEntities());
config.BeforeBindMapping += (sender, args) => args.Mapping.autoimport = false;
Factory = config.BuildSessionFactory();
Notice that I set up autoimport=false, but I still get an DuplicateMappingException from NHibernate:
nhibernate.duplicatemappingexception: duplicate import:
User refers to both
MyApp.VersionA,
... and
MyApp.VersionB.User,
... (try using auto-import="false")
Alexander, try this:
var assemblies =
AppDomain.CurrentDomain.GetAssemblies().Where(a => a.GetName().Name.Contains(".Infrastructure"));
foreach (var assembly in assemblies)
{
var mapper = new ModelMapper();
mapper.AddMappings(assembly.GetExportedTypes()
.Where(t => t.BaseType != null && t.BaseType.IsGenericType &&
t.BaseType.GetGenericTypeDefinition() == typeof (ClassMapping<>)));
var compileMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
compileMapping.autoimport = false;
configuration.AddMapping(compileMapping);
}
Related
Is there a way to select all the properties in a collection and set one without verbosly remapping the entire property list?
return =
_input.Where(
w => w.MaterialNumber.Contains("foo")
).Select(s => new Material.list() { ID = s.ID, MaterialNumber = s.MaterialNumber, orColor = "#303030" }).ToList()
);
Looking for something simpler.
return =
_input.Where(
w => w.MaterialNumber.Contains("foo")
).Select(s => new Material.list() {s, new orColor = "#303030" }).ToList()
);
You mentioned EF 6 but you don't actually use it in the question. Also you mentioned mapping, but are you sure if it is required? If it is possible for other code to use same instance without remapping, just use any approach listed below to set property of the original object
using System.Linq;
namespace ConsoleApp1
{
class DTO
{
public string Color { get; set; }
}
internal class Program
{
static void Main(string[] args)
{
var input = Enumerable.Repeat(new DTO(), 10);
// select statement
var selectOutput = input.Select(x =>
{
x.Color = "#303030";
return x;
});
// ForEach extension
var listOutput = input.ToList();
listOutput.ForEach(x => x.Color = "#303030");
// regular foreach
foreach (var inputItem in input)
{
inputItem.Color = "#303030";
}
}
}
}
Suppose I have the following:
public interface IFileHandler<TLocation,TRow> { ... }
//loads file in some location using record format defined in RowTypeA
//e.g. RowTypeA records exist in files that match string 'file_a.csv'
public class FileHandlerA<TLocation> : IFileHandler<TLocation, RowTypeA>{ ... }
//loads file in some location using record format defined in RowTypeB
//e.g. RowTypeB records exist in files that match string 'file_b.csv'
public class FileHandlerB<TLocation> : IFileHandler<TLocation, RowTypeB>{ ... }
public class MyCode {
...
public void MyMethod()
{
//here is how I would like to resolve file handlers
var fh1 = container.Resolve<IFileHandler<Location1, RowTypeA>>(); //resolves to FileHandlerA<Location1>
var fh2 = container.Resolve<IFileHandler<Location2, RowTypeA>>(); //resolves to FileHandlerA<Location2>
var fh3 = container.Resolve<IFileHandler<Location1, RowTypeB>>(); //resolves to FileHandlerB<Location1>
}
...
}
How do I do the registration in Castle Windsor for this? Or is there a better design for this problem?
P.S.
I tried:
Classes
.FromAssembly(thisAssembly)
.BasedOn(typeof(IFileHandler<,>)
.WithServiceAllInterfaces();
Also thought about this:
Component
.For<IFileHandler<,>()
.ImplementedBy<???>
I think this should work but haven't tested it:
var locationTypes = typeof(ILocation).Assembly.GetTypes()
.Where(t => !t.IsInterface && !t.IsGenericType).ToArray();
var fileHandlerTypes = typeof(IFileHandler<,>).Assembly.GetTypes()
.Where(t => !t.IsInterface && !t.IsGenericType && t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IFileHandler<,>))).ToArray();
foreach (var fh in fileHandlerTypes)
foreach(var locType in locationTypes)
{
var rowType = fh.BaseType.GenericTypeArguments[1];
var requestedType = typeof(IFileHandler<,>).MakeGenericType(locType).MakeGenericType(rowType);
container.Register(Component.For(requestedType, fh));
}
I need to map an object to another one using AutoMapper. The tricky question is how can I access an instance of the mapper (instance of IMapper) inside of the mapping configuration or inside of a custom type converter?
The code below does not work, however it is an example of what I would like to achieve - please notice the mapper.Map calls and assume that mappings Customer => CustomerDto and Customer => DetailedCustomerDto are defined.
var config = new MapperConfiguration(
cfg => cfg.CreateMap<Order, OrderDto>()
.ForMember(dst => dst.Customer, src => src.ResolveUsing(o => {
return o.Type == 1
? mapper.Map<Customer, CustomerDto>(o.Customer)
: mapper.Map<Customer, DetailedCustomerDto>(o.Customer)
})
);
The client part is:
var mapper = config.CreateMapper();
var orderDto = mapper.Map<Order, OrderDto>(order);
The simplified version of objects I want to map is:
public class Order
{
public int Type { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public long Id { get; set; }
public string Name { get; set; }
}
public class OrderDto
{
public CustomerDto Customer { get; set; }
}
public class CustomerDto
{
public long Id { get; set; }
}
public class DetailedCustomerDto : CustomerDto
{
public string Name { get; set; }
}
As you see from the code above, based on the value of Order.Type, the mapper should map the property Order.Customer to different targets. As one target (DetailedCustomerDto) inherits from the other one (CustomerDto) it becomes a bit tricky.
Please notice that usage of the obsolete and deprecated static method Mapper.Map is NOT an option.
As of AutoMapper 8.0 and up
The answer below for 5.1.1 still applies, but note that the use of ResolveUsing has been replaced with an overload of MapFrom, but the signature has otherwise remained consistent.
As of AutoMapper 5.1.1
You can get to the mapper using another overload of ResolveUsing with four parameters, fourth of which is ResolutionContext (context.Mapper):
var config = new MapperConfiguration(
cfg => {
cfg.CreateMap<Customer, CustomerDto>();
cfg.CreateMap<Customer, DetailedCustomerDto>();
cfg.CreateMap<Order, OrderDto>()
.ForMember(dst => dst.Customer, src => src.ResolveUsing((order, orderDto, i, context) => {
return order.Type == 1
? context.Mapper.Map<Customer, CustomerDto>(order.Customer)
: context.Mapper.Map<Customer, DetailedCustomerDto>(order.Customer);
}));
});
var orderTypeOne = new Order();
orderTypeOne.Type = 1;
orderTypeOne.Customer = new Customer() {
Id = 1
};
var dto = config.CreateMapper().Map<Order, OrderDto>(orderTypeOne);
Debug.Assert(dto.Customer.GetType() == typeof (CustomerDto));
var orderTypeTwo = new Order();
orderTypeTwo.Type = 2;
orderTypeTwo.Customer = new Customer() {
Id = 1
};
dto = config.CreateMapper().Map<Order, OrderDto>(orderTypeTwo);
Debug.Assert(dto.Customer.GetType() == typeof (DetailedCustomerDto));
Prior to AutoMapper 5.1.1
You can get to the mapper using another overload of ResolveUsing with two parameters, first of which is ResolutionResult (result.Context.Engine.Mapper):
var config = new MapperConfiguration(
cfg => {
cfg.CreateMap<Customer, CustomerDto>();
cfg.CreateMap<Customer, DetailedCustomerDto>();
cfg.CreateMap<Order, OrderDto>()
.ForMember(dst => dst.Customer, src => src.ResolveUsing((result, order) => {
return order.Type == 1
? result.Context.Engine.Mapper.Map<Customer, CustomerDto>(order.Customer)
: result.Context.Engine.Mapper.Map<Customer, DetailedCustomerDto>(order.Customer);
}));
});
var orderTypeOne = new Order();
orderTypeOne.Type = 1;
orderTypeOne.Customer = new Customer() {
Id = 1
};
var dto = config.CreateMapper().Map<Order, OrderDto>(orderTypeOne);
Debug.Assert(dto.Customer.GetType() == typeof (CustomerDto));
var orderTypeTwo = new Order();
orderTypeTwo.Type = 2;
orderTypeTwo.Customer = new Customer() {
Id = 1
};
dto = config.CreateMapper().Map<Order, OrderDto>(orderTypeTwo);
Debug.Assert(dto.Customer.GetType() == typeof (DetailedCustomerDto));
In addition to Evk's great answer, which helped me, if you need to do a mapping inside a mapping inside a config/profile that requires a custom constructor (i.e. the type has no default constructor), the following will work in v5.2.0:
CreateMap<Models.Job, Models.API.Job>(MemberList.Source);
CreateMap<StaticPagedList<Models.Job>, StaticPagedList<Models.API.Job>>()
.ConstructUsing((source, context) => new StaticPagedList<Models.API.Job>(
context.Mapper.Map<List<Models.Job>, List<Models.API.Job>>(source.ToList()),
source.PageNumber,
source.PageSize,
source.TotalItemCount));
In this example I'm mapping the X.PagedList custom collection type of one object type onto an equivalent collection of another object type. The first parameter to the lamdba expression is your source object, the second is your ResolutionContext from which you can access a mapper instance to map from.
I'm using Automapper 9 and the answers above didn't work for me.
Then for resolve my problem that is like yours I use .afterMap, like that:
public class AutoMapperOrder : Profile
{
public AutoMapperOrder()
{
CreateMap<Customer, CustomerDto>()
//...
CreateMap<Customer, DetailedCustomerDto>()
//...
CreateMap<Order, OrderDto>()
.AfterMap((src, dest, context) => {
dest.Customer = src.Type == 1
? context.Mapper.Map<Customer, CustomerDto>(src.Customer)
: context.Mapper.Map<Customer, DetailedCustomerDto>(src.Customer)
}
}
}
}
I hope to help somebody.
Assume that I have the following class structure:
public class Outer
{
[Dependency]
public Func<Inner> InnerFactory { get; set; }
}
public class Inner
{
}
In Autofac this can be done easily in the following way (and describes the behaviour I am looking for; ignore the fact that this is a stupid contrived example):
[TestMethod]
public void AutofacMakesThisEasy()
{
var builder = new ContainerBuilder();
builder.RegisterType<Outer>().PropertiesAutowired();
builder.RegisterType<Inner>().InstancePerOwned<Outer>();
var container = builder.Build();
var outer1 = container.Resolve<Owned<Outer>>().Value;
var inner1 = outer1.InnerFactory();
var inner2 = outer1.InnerFactory();
var outer2 = container.Resolve<Owned<Outer>>().Value;
var inner3 = outer2.InnerFactory();
var inner4 = outer2.InnerFactory();
Assert.AreNotSame(outer1, outer2, "outer1 == outer2");
Assert.AreSame(inner1, inner2, "inner1 != inner2");
Assert.AreNotSame(inner2, inner3, "inner2 == inner3");
Assert.AreSame(inner3, inner4, "inner3 != inner4");
}
How can I achieve the same behaviour in unity so the following test passes?
[TestMethod]
public void UnityHasMeScratchingMyHead()
{
var container = new UnityContainer();
//// What shoud I do here?
var outer1 = container.Resolve<Outer>();
var inner1 = outer1.InnerFactory();
var inner2 = outer1.InnerFactory();
var outer2 = container.Resolve<Outer>();
var inner3 = outer2.InnerFactory();
var inner4 = outer2.InnerFactory();
Assert.AreNotSame(outer1, outer2, "outer1 == outer2");
Assert.AreSame(inner1, inner2, "inner1 != inner2");
Assert.AreNotSame(inner2, inner3, "inner2 == inner3");
Assert.AreSame(inner3, inner4, "inner3 != inner4");
}
Note: I would dearly love to ditch Unity for a decent IoC, but that is going to be a very hard sell.
If InnerFactory was just Inner instead of Func<Inner> The solution would be PerResolveLifetimeManager
[TestMethod]
public void UnityHasMeScratchingMyHead()
{
var container = new UnityContainer();
container.RegisterType<Inner>(new PerResolveLifetimeManager());
var outer1 = container.Resolve<Outer>();
//... and so on.
However because you have a factory you need to make it a little more complicated. You need to make the factory PerResolve then have the objects the factory makes all the same instance (ContainerControlledLifetimeManager). You do that via the following:
[TestMethod]
public void UnityHasMeScratchingMyHead()
{
var container = new UnityContainer();
container.RegisterType<Func<Inner>>(new PerResolveLifetimeManager(), new InjectionFactory(x =>
{
var child = x.CreateChildContainer();
child.RegisterType<Inner>(new ContainerControlledLifetimeManager());
return new Func<Inner>(() => child.Resolve<Inner>());
}));
var outer1 = container.Resolve<Outer>();
var inner1 = outer1.InnerFactory();
var inner2 = outer1.InnerFactory();
var outer2 = container.Resolve<Outer>();
var inner3 = outer2.InnerFactory();
var inner4 = outer2.InnerFactory();
Assert.AreNotSame(outer1, outer2, "outer1 == outer2");
Assert.AreSame(inner1, inner2, "inner1 != inner2");
Assert.AreNotSame(inner2, inner3, "inner2 == inner3");
Assert.AreSame(inner3, inner4, "inner3 != inner4");
}
One thing of note, Unity is easily extensible. If you are going to be doing this frequently with a little work you could make a InstancePerOwnedLifetimeManager<T> and just use that and not need to worry about generating factories at all.
I'm doing some complex modifications to our EF model (we're using code-first) and I know it should affect my database in particular and testable ways; for instance, I should be able to assert;
The db will have an 'Item' table
'Item' will have an integer 'Id' field which is the primary key
'Item' will have a 50-character string 'Name' field
These are ripe for unit testing, but I can't find a way to test these kinds of assertion.
What I'd like is a way to get the database model from the DbContext, so that I can do something like;
var model = BuildModel(MyEntityContext);
var itemTable = model.Db.Tables["Item"]
Assert.IsNotNull(itemTable);
Assert.IsTrue(itemTable.Columns["Id"] != null);
Assert.IsTrue(itemTable.Columns["Name"] != null);
Assert.IsTrue(itemTable.Columns["Name"].Length == 50);
...
Does anyone know of a way to get hold of a description of the database structure implied by a DbContext object?
you could start with something like this...see if this takes you anywhere.
using(ObjectContext context = new ObjectContext())
{
var queryResult = from meta in context.MetadataWorkspace.GetItems(DataSpace.CSpace)
.Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
from p in (meta as EntityType).Properties
.Where(p => p.DeclaringType.Name == context.GetType().Name
&& p.Name == PropertyName
Select new {Length = p.TypeUsage.Facets["MaxLength"].Value, Name=p.TypeUsage.Facets["Name"].Value, p.TypeUsage.Facets["FacetType"].Value
}
(#steve-cooper) A really helpful start! thanks. I've come up with a working class based closely on your suggestion -- I've stuck it here so I can give you the accepted answer, and so others can see the worked-up code.
public class ModelSummary
{
public Dictionary<string, System.Data.Metadata.Edm.EntityType> Entities { get; private set; }
public static ModelSummary Load(DbContext context)
{
var adapter = (IObjectContextAdapter)context;
var objectContext = adapter.ObjectContext;
var summary = new ModelSummary();
var items = objectContext.MetadataWorkspace.GetItems(DataSpace.SSpace);
summary.Entities =
objectContext.MetadataWorkspace.GetItems(DataSpace.SSpace)
.OfType<EntityType>()
.ToDictionary(et => et.Name);
return summary;
}
public bool EntityExists(string entityName)
{
return this.Entities.ContainsKey(entityName);
}
public bool EntityHasProperty(string entityName, string propertyName)
{
if (!EntityExists(entityName))
{
return false;
}
var entity = this.Entities[entityName];
return entity.Properties.Contains(propertyName);
}
}
And the test looks like this;
[Test]
public void Context_SchemaIsExpected()
{
var summary = ModelSummary.Load(new MyContext());
Assert.IsTrue(summary.EntityExists("Item"));
Assert.IsTrue(summary.EntityHasProperty("Item", "Id"));
}