我在 ITypeConverter 中使用 AutoMapper ,我想保留 Castle Windsor 中的所有内容。 在一个程序集中,我有 ITypeCoverter ,我使用这种方法加载它们:
container
.Register(Types.FromAssembly(Assembly.GetExecutingAssembly())
.BasedOn(typeof(ITypeConverter<,>)));
到目前为止,我可以看到Windsor正在正确加载我的所有转换器。
然后我在Windsor中注册AutoMapper
Mapper.Initialize(m => m.ConstructServicesUsing(container.Resolve));
container.Register(Component.For<IMappingEngine>().Instance(Mapper.Engine));
但是当我问一个IMappingEngine的实例时,没有加载约定。我在这里想念一下吗?
答案 0 :(得分:3)
我让AutoMapper和Windsor与Profiles和TypeConverters很好地配合使用。我认为这对你来说应该是不可知的,因为AutoMapper会自动获取ITypeConverter的任何实现。
如果它能解决您的问题,请告诉我。
首先我向温莎注册了AutoMapper:
public class AutoMapperInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// Replace by whatever assembly contains your ITypeConverter, IValueResolver and Profile implementations
var myAssembly = Classes.FromAssemblyNamed("MyAssembly");
// Register AutoMapper such that it uses a singleton configuration
container.Register(
myAssembly.BasedOn(typeof(ITypeConverter<,>)).WithServiceSelf(),
myAssembly.BasedOn<IValueResolver>().WithServiceBase(),
myAssembly.BasedOn<Profile>().WithServiceBase(),
Component.For<IEnumerable<IObjectMapper>>().UsingFactoryMethod(() => MapperRegistry.Mappers),
Component.For<ConfigurationStore>()
.LifestyleSingleton()
.UsingFactoryMethod(x =>
{
var typeMapFactory = x.Resolve<ITypeMapFactory>();
var mappers = x.Resolve<IEnumerable<IObjectMapper>>();
ConfigurationStore configurationStore = new ConfigurationStore(typeMapFactory, mappers);
configurationStore.ConstructServicesUsing(x.Resolve);
configurationStore.AssertConfigurationIsValid();
return configurationStore;
}),
Component.For<IConfigurationProvider>().UsingFactoryMethod(x => x.Resolve<ConfigurationStore>()),
Component.For<IConfiguration>().UsingFactoryMethod(x => x.Resolve<ConfigurationStore>()),
Component.For<IMappingEngine>().ImplementedBy<MappingEngine>().LifestyleSingleton(),
Component.For<ITypeMapFactory>().ImplementedBy<TypeMapFactory>()
);
// Add all Profiles
var configuration = container.Resolve<IConfiguration>();
container.ResolveAll<Profile>().ToList().ForEach(configuration.AddProfile);
}
}
然后我创建了一个配置文件,我在其中使用一些反射注册了所有的ITypeConverter实现:
public class TypeConverterProfile : Profile
{
private readonly IConfiguration _configuration;
public TypeConverterProfile(IConfiguration configuration)
{
_configuration = configuration;
}
protected override void Configure()
{
// Replace by whatever assembly contains your ITypeConverter implementations
var myAssembly = Classes.FromAssemblyNamed("MyAssembly");
var typeConverters =
from x in myAssembly.GetTypes()
from type in x.GetInterfaces()
where type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ITypeConverter<,>)
select new
{
Type = x,
Source = type.GetGenericArguments()[0],
Destination = type.GetGenericArguments()[1]
};
// Apply type converters to AutoMapper configuration
foreach (var typeConverter in typeConverters)
_configuration.CreateMap(typeConverter.Source, typeConverter.Destination).ConvertUsing(typeConverter.Type);
}
}
AutoMapper现在将自动选择并使用&#34; MyAssembly&#34;中的任何Profiles和ITypeConverters实现。
例如,您可能有个人资料:
public class MapProfile : Profile
{
private readonly IConfiguration _configuration;
public MapProfile(IConfiguration configuration)
{
_configuration = configuration;
}
protected override void Configure()
{
// Create an auto-map from SearchResultModel -> SearchResult
_configuration.CreateMap<SearchResultModel, SearchResult>();
}
}
和一个ITypeConverter:
public class SearchRequestConverter : ITypeConverter<SearchRequest, SearchRequestModel>
{
private readonly IConfiguration _configuration;
public MapProfile(IConfiguration configuration)
{
// Also in the ITypeConverter you may have the IConfiguration injected in case you need it
_configuration = configuration;
}
public SearchRequestModel Convert(ResolutionContext context)
{
var model = (SearchRequest) context.SourceValue;
return new SearchRequestModel
{
Results = model.Results
};
}
}
最后,通过依赖IMappingEngine来执行类中的实际映射:
public class FolderRepository
{
private readonly IMappingEngine _mappingEngine;
public FolderRepository(IMappingEngine mappingEngine)
{
_mappingEngine = mappingEngine;
}
public SearchResult Search(SearchRequest searchRequest)
{
// This mapping will use the ITypeConverter implementation
SearchRequestModel searchRequestModel = _mappingEngine.Map<SearchRequestModel>(searchRequest);
SearchResultModel searchResultModel = Search(searchRequestModel);
// This mapping will use the auto-map from the Profile
SearchResult searchResult = _mappingEngine.Map<SearchResultModel>(searchResultModel);
return searchResult;
}
private SearchResultModel Search(SearchRequestModel searchRequestModel)
{
SearchResultModel result = new SearchResultModel();
// ... perform search ...
return result;
}
}
要拥有更多的ITypeConverters,您只需要实现它们,它们将自动被Windsor和AutoMapper选中。可以在配置文件中添加手动自动映射(CreateMap&lt;&gt;)。
这能解决您的问题吗?
答案 1 :(得分:1)
我看不到创建/设置映射的代码。既不Mapper.CreateMap<Source, Destination>();
也不configuration.CreateMap<Source, Destination>();
不幸的是,关于一起使用IoC和AutoMapper的信息还不够。您只能找到一个an example of usage AutoMapper and Structure Map in the official samples。
还有my example of usage AutoMapper and Castle Windsor。它与前一个类似,但使用Castle Windsor而不是Structure Map。
/// <summary>
/// Castle Windsor example.
/// </summary>
/// <remarks>
/// StructureMap example
/// see https://github.com/AutoMapper/AutoMapper/blob/develop/src/AutoMapperSamples/CastleWindsorIntegration.cs
/// </remarks>
public class CastleWindsorIntegration
{
private readonly IWindsorContainer container;
public CastleWindsorIntegration()
{
container = new WindsorContainer();
}
[Fact]
public void Example()
{
container.Install(new ConfigurationInstaller());
var configuration1 = container.Resolve<IConfiguration>();
var configuration2 = container.Resolve<IConfiguration>();
configuration1.Should().BeSameAs(configuration2);
var configurationProvider = container.Resolve<IConfigurationProvider>();
configurationProvider.Should().BeSameAs(configuration1);
var configuration = container.Resolve<ConfigurationStore>();
configuration.Should().BeSameAs(configuration1);
configuration1.CreateMap<Source, Destination>();
var engine = container.Resolve<IMappingEngine>();
var destination = engine.Map<Source, Destination>(new Source { Value = 15 });
destination.Value.Should().Be(15);
}
[Fact]
public void Example2()
{
container.Install(new MappingEngineInstaller());
Mapper.Reset();
Mapper.CreateMap<Source, Destination>();
var engine = container.Resolve<IMappingEngine>();
var destination = engine.Map<Source, Destination>(new Source { Value = 15 });
destination.Value.Should().Be(15);
}
public class Source
{
public int Value { get; set; }
}
public class Destination
{
public int Value { get; set; }
}
public class ConfigurationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IEnumerable<IObjectMapper>>()
.LifestyleSingleton()
.UsingFactoryMethod(() => MapperRegistry.Mappers),
Component.For<ConfigurationStore>().ImplementedBy<ConfigurationStore>(),
Component.For<IConfigurationProvider>().UsingFactoryMethod(k => k.Resolve<ConfigurationStore>()),
Component.For<IConfiguration>().UsingFactoryMethod(k => k.Resolve<ConfigurationStore>()),
Component.For<IMappingEngine>().ImplementedBy<MappingEngine>(),
Component.For<ITypeMapFactory>().ImplementedBy<TypeMapFactory>());
}
}
public class MappingEngineInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IMappingEngine>().UsingFactoryMethod(() => Mapper.Engine));
}
}
}
为了使测试变为绿色,例如需要使用Mapper.CreateMap<Source, Destination>().ConvertUsing<SourceToDestinqtionConvertor>();
。
[Fact]
public void Example3()
{
container
.Register(Types.FromAssembly(Assembly.GetExecutingAssembly())
.BasedOn(typeof(ITypeConverter<,>)));
Mapper.Initialize(m => m.ConstructServicesUsing(container.Resolve));
container.Register(Component.For<IMappingEngine>().Instance(Mapper.Engine));
var engine = container.Resolve<IMappingEngine>();
Mapper.CreateMap<Source, Destination>().ConvertUsing<SourceToDestinqtionConvertor>();
var destination = engine.Map<Source, Destination>(new Source { Value = 15 });
destination.Value.Should().Be(15);
}
public class SourceToDestinqtionConvertor : ITypeConverter<Source, Destination>
{
public Destination Convert(ResolutionContext context)
{
throw new System.NotImplementedException();
}
}
编辑:
为了能够解决&#39; ITypeConverter&#39;需要指定要使用的服务。
container
.Register(Types.FromAssembly(Assembly.GetExecutingAssembly())
.BasedOn(typeof(ITypeConverter<,>))
.WithService.AllInterfaces());
// Makes sure that type converter can be resolved
var resolver = container.Resolve<ITypeConverter<Source, Destination>>();
resolver.Should().BeOfType<SourceToDestinqtionConvertor>();
答案 2 :(得分:0)
我执行以下操作以使Automapper工作。
注册点第一名:
foreach (var automapperProfileType in types.Where(t => t.IsInterface == false && typeof(Profile).IsAssignableFrom(t)))
{
container.Register(
Component.For(typeof(Profile))
.ImplementedBy(automapperProfileType)
.LifestyleTransient()
.Named("AutoMapper / Profile / " + automapperProfileType.FullName));
automapperProfileTypes.Add(automapperProfileType);
}
然后在所有类型的初始化之后:
foreach (var profileMap in container.ResolveAll<Profile>())
{
Mapper.AddProfile(profileMap);
}
希望有所帮助。