I am using mapping by convention and have issues when adding profile to the configuration. Consider configuration below. I am using AutoFac to resolve profiles in CoreMapper and the profiles are correctly injected.
Mapping configuration
public CoreMapper(IEnumerable<Profile> profiles)
{
MapperConfiguration = new MapperConfiguration(cfg =>
{
cfg.CreateMissingTypeMaps = true;
cfg.AllowNullCollections = true;
cfg.AllowNullDestinationValues = true;
cfg.ForAllMaps((mapType, mapperExpression) =>
{
mapperExpression.PreserveReferences();
mapperExpression.MaxDepth(10);
});
cfg.IgnoreUnmapped();
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
cfg.CreateMap<string, string>().ConvertUsing(str => string.IsNullOrEmpty(str) ? null : str);
});
Mapper = MapperConfiguration.CreateMapper();
}
IgnoreUnmapped is as follows:
private static void IgnoreUnmappedProps(TypeMap map, IMappingExpression expression)
{
foreach(var propName in map.GetUnmappedPropertyNames())
{
if (map.SourceType.GetProperty(propName) != null)
expression.ForSourceMember(propName, opt => opt.Ignore());
if (map.DestinationType.GetProperty(propName) != null)
expression.ForMember(propName, opt => opt.Ignore());
}
}
public static void IgnoreUnmapped(this IProfileExpression profile)
{
profile.ForAllMaps(IgnoreUnmappedProps);
}
In my code I have a generic class implementation with the line like this:
mapper.Map<TPoco>(entity);
Note: mapper is an instance of CoreMapper from above.
where TPoco is POCO model defined like:
public class ModelPoco : IModel {
// props
}
and entity is database entity model.
The mapping works fine. The result of mapper.Map< TPoco>(entity) is correct.
I then proceed and add a profile for a specific map that is not at all related to the ModelPoco being mapped before.
The profile being added:
public class RepositoryLayerProfile : AutoMapper.Profile {
public RepositoryLayerProfile() {
CreateMap<SomeOtherEntity, ISomeOtherModelInterface>();
}
}
Version: 6.2.2
Expected behavior
Mapping of ModelEntity to ModelPoco should happen normally.
Actual behavior
The mapping breaks with the message:
Unable to cast object of type 'Proxy< IModel>' to type 'ModelPoco'. on line mapper.Map(entity);
I am not sure why does it create Proxy class for IModel interface and then tries to cast to concrete implementation?
I explicitly set that I want to map entity to a concrete implementation.
If I remove CreateMap from the profile it works fine, but the first time I define CreateMap in the said profile, it breaks.
It seems to me like it forgets about the configuration for some reason even tho it has nothing to do with it.
Related
Although I'm relatively new to AutoMapper I'm using it in a small project I'm developing. I've never had problems using it before but now I'm facing some weird behavior passing parameters to a Custom Resolver.
Here's the scenario: I get a list of messages from my repository and then map those to a frontend friendly version of it. Nothing fancy, just some normal mapping between objects. I have a field in that frontend object that tells if a certain user already voted for that message and that's what I'm using the Custom Resolver for (it's that second "ForMember"):
public List<SupportMessageUi> GetAllVisible(string userId)
{
Mapper.CreateMap<SupportMessage, SupportMessageUi>()
.ForMember(dest => dest.Votes,
opt => opt.ResolveUsing<SupportMessageVotesResolver>())
.ForMember(dest => dest.UserVoted,
opt => opt.ResolveUsing<SupportMessagesUserVotedResolver>()
.ConstructedBy(() => new SupportMessagesUserVotedResolver(userId)));
var messages = _unitOfWork.MessagesRepository.Get(m => m.Visible);
var messagesUi = Mapper.Map<List<SupportMessageUi>>(messages);
return messagesUi;
}
I'm calling this method on a web service and the problem is: the first time I call the webservice (using the webservice console) it all runs perfectly. For example, if I pass '555' as the userId I get to this method with the correct value:
And in the Custom Resolver the value was correctly passed to the constructor:
The results returned are correct. The problem comes next. The second time I call the service, passing a different argument ('666' this time) the argument that gets to the constructor of the Custom Resolver is the old one ('555'). Here's what I mean:
Right before mapping the objects we can see that the value passed to the constructor was correct ('666'):
But when it gets to the constructor of the Resolver the value is wrong, and is the old one ('555'):
All subsequent calls to the service use the original value in the Custom Resolver constructor ('555'), independently of the value I pass to the service (also happens if I make the call from another browser). If I shut down the server and relaunch it I can pass a new parameter (that will be used in all other calls until I shut it down again).
Any idea on why this is happening?
It's happening because AutoMapper.CreateMap is a static method, and only needs to be called once. With the CreateMap code in your web method, you're trying to call it every time you call that method on your web service. Since the web server process stays alive between calls (unless you restart it, like you said) then the static mappings stay in place. Hence, the necessity of calling AutoMapper.Reset, as you said in your answer.
But it's recommended that you put your mapping creation in AppStart or Global or a static constructor or whatever, so you only call it once. There are ways to call Map that allow you to pass in values, so you don't need to try to finesse things with the constructor of your ValueResolver.
Here's an example using a ValueResolver (note the change to implementing IValueResolver instead of inheriting ValueResolver<TSource, TDestination>):
[Test]
public void ValueTranslator_ExtraMapParameters()
{
const int multiplier = 2;
ValueTranslator translator = new ValueTranslator();
Mapper.AssertConfigurationIsValid();
ValueSource source = new ValueSource { Value = 4 };
ValueDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(8));
source = new ValueSource { Value = 5 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(10));
}
private class ValueTranslator
{
static ValueTranslator()
{
Mapper.CreateMap<ValueSource, ValueDest>()
.ForMember(dest => dest.Value, opt => opt.ResolveUsing<ValueResolver>().FromMember(src => src.Value));
}
public ValueDest Translate(ValueSource source, int multiplier)
{
return Mapper.Map<ValueDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class ValueResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
return source.New((int)source.Value * (int)source.Context.Options.Items["multiplier"]);
}
}
}
private class ValueSource { public int Value { get; set; } }
private class ValueDest { public int Value { get; set; } }
And here's an example using a TypeConverter:
[Test]
public void TypeTranslator_ExtraMapParameters()
{
const int multiplier = 3;
TypeTranslator translator = new TypeTranslator();
Mapper.AssertConfigurationIsValid();
TypeSource source = new TypeSource { Value = 10 };
TypeDest dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(30));
source = new TypeSource { Value = 15 };
dest = translator.Translate(source, multiplier);
Assert.That(dest.Value, Is.EqualTo(45));
}
private class TypeTranslator
{
static TypeTranslator()
{
Mapper.CreateMap<TypeSource, TypeDest>()
.ConvertUsing<TypeConverter>();
}
public TypeDest Translate(TypeSource source, int multiplier)
{
return Mapper.Map<TypeDest>(source, opt => opt.Items.Add("multiplier", multiplier));
}
private class TypeConverter : ITypeConverter<TypeSource, TypeDest>
{
public TypeDest Convert(ResolutionContext context)
{
TypeSource source = (TypeSource)context.SourceValue;
int multiplier = (int)context.Options.Items["multiplier"];
return new TypeDest { Value = source.Value * multiplier };
}
}
}
private class TypeSource { public int Value { get; set; } }
private class TypeDest { public int Value { get; set; } }
Answering myself: I was not using AutoMapper.Reset(). Once I did that everything started working properly.
Helpful reading: http://www.markhneedham.com/blog/2010/01/27/automapper-dont-forget-mapper-reset-at-the-start/
Is it possible to use a simple action method - just like with Caliburn.Micro - instead of a command with MvvmCross bindings?
Example:
public void Action()
{
Tip = 11;
}
<Button
android:text="Button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/button1"
local:MvxBind="Click Action" />
It doesn't work out of the box, I tested that.
While I found a lot of samples about adding new target bindings, I didn't find a single one about adding a new source binding.
UPDATE:
This works now out of the box with the Rio binding. To use it, add the MvvmCross MethodBinding NuGet package to the Android project.
Up until now, much of the emphasis for MvvmCross has been on allowing multi-platform target binding with the source remaining mainly 'vanilla' INotifyPropertyChanged.
There have been some deviation in terms of ViewModel structure - e.g.:
the MvxCommandCollection - http://slodge.blogspot.co.uk/2013/03/fixing-mvvm-commands-making-hot-tuna.html
some users using Fody - http://twincoders.com/blog/codigo-limpio-con-fody/
Recently, several new feature requests have also been logged in this area:
AutoCommands - I think this is what you are asking about here - https://github.com/slodge/MvvmCross/issues/301
Rio binding sources - https://github.com/slodge/MvvmCross/issues/299
Tibet binding - https://github.com/slodge/MvvmCross/issues/298
Because of these, I do expect more functionality to be exposed in this area in the future...
With that said, if you wanted to get this working today, then MvvmCross Binding is overrideable so you could fairly easily do it:
1. Implement an ICommand that invokes a MethodInfo using reflection (for completeness this should probably also use a parameter if available) - some kind of InvokeMethodCommand (code for this left to the reader!)
.
2. Implement an MyMethodSourceBinding class which wraps the InvokeMethodCommand - something like:
public class MyMethodSourceBinding : MvxSourceBinding
{
private readonly MethodInfo _methodInfo;
protected MyMethodSourceBinding(object source, MethodInfo methodInfo)
: base(source)
{
_methodInfo = _methodInfo;
}
public override void SetValue(object value)
{
// do nothing - not allowed
}
public override Type SourceType
{
get { return typeof(ICommand); }
}
public override bool TryGetValue(out object value)
{
value = new InvokeMethodCommand(source, _methodInfo);
return true;
}
}
3. Override MvvmCross's registered IMvxSourceBindingFactory with your own implementation that can detect when a method is present - sadly most of this is cut and paste coding today - it would be something like
public class MySourceBindingFactory
: IMvxSourceBindingFactory
{
private IMvxSourcePropertyPathParser _propertyPathParser;
private IMvxSourcePropertyPathParser SourcePropertyPathParser
{
get
{
if (_propertyPathParser == null)
{
_propertyPathParser = Mvx.Resolve<IMvxSourcePropertyPathParser>();
}
return _propertyPathParser;
}
}
public IMvxSourceBinding CreateBinding(object source, string combinedPropertyName)
{
var tokens = SourcePropertyPathParser.Parse(combinedPropertyName);
return CreateBinding(source, tokens);
}
public IMvxSourceBinding CreateBinding(object source, IList<MvxPropertyToken> tokens)
{
if (tokens == null || tokens.Count == 0)
{
throw new MvxException("empty token list passed to CreateBinding");
}
var currentToken = tokens[0];
if (tokens.Count == 1)
{
return CreateLeafBinding(source, currentToken);
}
else
{
var remainingTokens = tokens.Skip(1).ToList();
return CreateChainedBinding(source, currentToken, remainingTokens);
}
}
private static MvxChainedSourceBinding CreateChainedBinding(object source, MvxPropertyToken propertyToken,
List<MvxPropertyToken> remainingTokens)
{
if (propertyToken is MvxIndexerPropertyToken)
{
return new MvxIndexerChainedSourceBinding(source, (MvxIndexerPropertyToken) propertyToken,
remainingTokens);
}
else if (propertyToken is MvxPropertyNamePropertyToken)
{
return new MvxSimpleChainedSourceBinding(source, (MvxPropertyNamePropertyToken) propertyToken,
remainingTokens);
}
throw new MvxException("Unexpected property chaining - seen token type {0}",
propertyToken.GetType().FullName);
}
private static IMvxSourceBinding CreateLeafBinding(object source, MvxPropertyToken propertyToken)
{
if (propertyToken is MvxIndexerPropertyToken)
{
return new MvxIndexerLeafPropertyInfoSourceBinding(source, (MvxIndexerPropertyToken) propertyToken);
}
else if (propertyToken is MvxPropertyNamePropertyToken)
{
//**************************
// Special code is here
var propertyToken = (MvxPropertyNamePropertyToken) propertyToken;
if (source != null)
{
var method = source.GetType().GetMethod(propertyToken.PropertyName, BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
if (method != null)
{
return new MyMethodSourceBinding(source, method);
}
}
return new MvxSimpleLeafPropertyInfoSourceBinding(source,
(MvxPropertyNamePropertyToken) propertyToken);
// Special code ends here
//**************************
}
else if (propertyToken is MvxEmptyPropertyToken)
{
return new MvxDirectToSourceBinding(source);
}
throw new MvxException("Unexpected property source - seen token type {0}", propertyToken.GetType().FullName);
}
}
4. Supply this source binding factory in your own custom binding builder - e.g.:
public class MyAndroidBindingBuilder
: MvxAndroidBindingBuilder
{
protected override IMvxSourceBindingFactory CreateSourceBindingFactory()
{
return new MvxSourceBindingFactory();
}
}
5. Supply this binding builder during your setup
public class Setup : MvxAndroidSetup
{
// ....
protected override MvxAndroidBindingBuilder CreateBindingBuilder()
{
return new MyAndroidBindingBuilder();
}
}
Note: This approach is only for advanced users right now... As suggested in the first part of this question, I do expect the code in this area to change quite a lot so you might also encounter some issues maintaining a fork in this area. (Indeed the code in this area has already changed quite significantly on the Tibet Binding branch within the GitHub repo!)
I'm using EF4.1 with MVC3 and I need an override to prevent EF from creating a db if it doesn't exist. Instead of creating a new db I would like to catch the error and report that the initial catalog (the database name) is invalid in the connect string.
However, during development I would like to allow for updates for new classes/properties to create according tables/cols in the database.
Is there a best practice or pattern here?
In my application i am completly disable context initializer and handle database mapping and schema manually.
For example :
public class AppDbContext : DbContext
{
public IDbSet<Account> Accounts { get; set; }
public AppDbContext() : base("connection_string")
{
Database.SetInitializer<AppDbContext>(null); // Important! Dont use entity framework initializer !important
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/* Register custom mapping class */
modelBuilder.Configurations.Add(new AccountMapper());
base.OnModelCreating(modelBuilder);
}
}
And custom mapping :
public class AccountMapper : EntityTypeConfiguration<Account>
{
/// <summary>
/// Employee entity mapper
/// </summary>
public AccountMapper()
{
ToTable("accounts");
HasKey(x => x.Id);
...
}
}
I would suggest looking into the EF database initializer, specifically the IDatabaseInitializer interface.
If you just want it to stop creating the database when it doesn't exist, then just set the Initializer to null. But if you want to log the event or something along those lines then simply create your own IDatabaseInitializer - it's not hard.
You can then set the initializer Application_Start in your global.asax.cs like so:
Database.SetInitializer(new YourCustomInitializer());
As a bonus, here's an example IDatabaseInitializer that I use to run database migrations (using FluentMigrator)... it's extremely handy if I do say so myself!
public class MigrationsDbContextInitializer : IDatabaseInitializer<YourDbContext>
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MigrationsDbContextInitializer));
public void InitializeDatabase(YourDbContext context)
{
var announcer = new BaseAnnouncer(x => Logger.Info(x));
var runnerContext = new RunnerContext(announcer)
{
Database = "sqlserver2008",
Connection = context.Database.Connection.ConnectionString,
Target = "YourEntitiesNamespace",
PreviewOnly = false,
Task = "migrate"
};
new TaskExecutor(runnerContext).Execute();
}
}
I'm currently registering a bunch of stuff at one point in my initialisation sequence
Container.Register(AllTypes.FromAssemblyContaining<MyAssembly>()
.BasedOn(typeof(IRepository<>))
.WithService.Self().Configure(c => c.LifeStyle.Transient));
I'm using WithService.Self so that it doesn't automatically pick up AllInterfaces, so that the interface that I will want to add later on as a type forward has not already been added.
I'd like then (later on) to be able to add a type forward to one of the already registered components, and Intellisense on the ForwardedTypes property suggested using .Forward(typof()) e.g.
Container.Register(Component.For<IOtherInterface>()
.Forward(typeof(IOtherInterface))
.ImplementedBy<AlreadyRegisteredType>().LifeStyle.Transient);
Is this possible?
EDIT:
I've been trying to get the stuff that Krzysztof has suggested working so I've generated a test project (below). I've tried various combinations to get the ConfigureFor to forward IMyInterface to MySecondType, but just can't get it to work, when done as a second step after initial registration of my component types. I'm probably being dim, but I'm just not getting how the ConfigureFor command works, and the documentation is a little sketchy (non-existant) on the subject.
namespace TestProject1
{
public class MyType : IMyInterface
{
public virtual string MyProperty { get; set; }
}
public class MySecondType : IMyInterface
{
public virtual string MySecondProperty { get; set; }
}
public interface IMyInterface
{
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
//New Container
var container = new WindsorContainer();
//Register Types
container.Register(
AllTypes.FromAssemblyContaining<MyType>().BasedOn<IMyInterface>().WithService.Self().Configure(
c => c.LifeStyle.Transient));
//Other stuff happens here...
//Now Register our interface as a forward
container.Register(AllTypes.FromAssemblyContaining<IMyInterface>()
.BasedOn<IMyInterface>()
.WithService.Base()
.ConfigureFor<IMyInterface>(r => r.Forward<MySecondType>()).Configure(c => c.LifeStyle.Transient));
var typeA = new MySecondType();
var typeB = container.Resolve<IMyInterface>();
Assert.IsInstanceOfType(typeB.GetType(), typeA.GetType());
}
}
}
What you described in the comment is registering another component for the AlreadyRegisteredType.
If you want to add a forward to the same component use
ConfigureFor<AlreadyRegisteredType>(c => c.Forward<IOtherInterface>())
full example:
Container.Register(AllTypes.FromThisAssembly()
.BasedOn<IEmptyService>()
.WithService.Base()
.ConfigureFor<EmptyServiceComposite>(r => r.Forward<EmptyServiceComposite>()));
Once you registered some type
Container.Register(Component.For<SomeType>());
you can forward some interface to it in this way:
Container.Register(Component.For<ISomeInterface>()
.UsingFactoryMethod<ISomeInterface>(kernel => kernel.Resolve<SomeType>()));
I am trying to learn how to use Castle Windsor IoC and am having some difficulties understanding how to configure some objects that I need to resolve dynamically. Basically, I have several implementations of IDataSource, and I need to choose the implementation to use based upon how a particular "data source" has been configured. So I might have quite alot of data sources configured to use one of the 3 implementations. My expectation is that the dependant code will take a dependency on a factory method which will give them the correct IDataSource when it is provided with the "data source id" along with the dependencies the data source implementations require (an IPrincipal).
I am struggling with how to correctly write the registration delegate for Windsor. Below is roughly what I've got. I'm trying to use the DynamicParameters method (which may not be the correct thing to use) to perform the logic which figures out which implementation to use and then calling Resolve to pull out that specific version. But I do not know how to return the resolved object, since DynamicParameters is expecting a ComponentReleasingDelegate, which I assume means it should be something like return k => { k.ReleaseComponent(dataSource); }. But then how do I yield the dataSource I've acquired back to the container for it to return to the caller?
struct DataSourceInfo {
string Id;
string ProviderType;
}
interface ICatalog : IDictionary<string /* Id */, DataSourceInfo> {
/* ... */
}
class Catalog : ICatalog {
/* implement dictionary which looks up DataSourceInfo from their string id */
}
interface IDataSource { /* ... */ }
class Source1 : IDataSource {
Source1(string id, IPrincipal principal) { /* ... */ }
}
class Source2 : IDataSource {
Source2(string id, IPrincipal principal) { /* ... */ }
}
/* ... */
/* ... inside Windsor configuration section */
container.Register(Component.For<ICatalog>().LifeStyle.Singleton.ImplementedBy<Catalog>());
// Default service provider is a factory method which uses the string (data source id)
// and looks up the DataSourceInfo from the ICatalog. It then uses info.ProviderType
// to request IoC to resolve that specific implementation and passes in "id" and "principal"
// to be used to resolve the dependencies of the implementation
container.Register(Component.For<IDataSource>().LifeStyle.Transient
.DynamicParameters((kernel, context, args) => {
if (args == null || !args.Contains("id") || !(args["id"] is string)) throw ApplicationException("bad args");
var id = (string)args["id"];
var catalog = kernel.Resolve<ICatalog>();
DataSourceInfo info;
try { info = catalog[id]; } finally { kernel.ReleaseComponent(catalog); }
// Now resolve the actual IDataSource
var dataSource = kernel.Resolve<IDataSource>(info.ProviderType, args);
// How do I return dataSource???
});
// Now register the actual implementations
container.Register(Component.For<IDataSource>().LifeStyle.Transient.ImplementedBy<Source1>().Named("Source1"));
container.Register(Component.For<IDataSource>().LifeStyle.Transient.ImplementedBy<Source2>().Named("Source2"));
/* ... */
/* some application startup code which configures some data sources */
class AppConfigurer {
AppConfigurer(ICatalog catalog) {
catalog["sourceA"] = new DataSourceInfo() { Id = "sourceA", ProviderType = "Source1" }; // data sourceA is provided by Source1 class
catalog["sourceB"] = new DataSourceInfo() { Id = "sourceB", ProviderType = "Source2" }; // data sourceB is provided by Source2 class
catalog["sourceC"] = new DataSourceInfo() { Id = "sourceC", ProviderType = "Source2" }; // data sourceC is provided by Source2 class
catalog["sourceD"] = new DataSourceInfo() { Id = "sourceD", ProviderType = "Source2" }; // data sourceD is provided by Source2 class
catalog["sourceE"] = new DataSourceInfo() { Id = "sourceE", ProviderType = "Source1" }; // data sourceE is provided by Source1 class
}
}
// Here is where I actually want to use IDataSources, and I do not want to know all the business about IDataSourceInfo. I just know a dataSourceId and an IPrincipal and want to get an IDataSource to work with.
class Dependant {
Dependant (Func<string, IPrincipal, IDataSource> factory) {
var sourceA = factory("sourceA", somePrincipal); // sourceA.GetType() == typeof(Source1)
var sourceB = factory("sourceB", somePrincipal); // sourceB.GetType() == typeof(Source2)
var sourceC = factory("sourceC", somePrincipal); // sourceC.GetType() == typeof(Source2)
}
}
Edit: by switching from DynamicParameters to UsingFactoryMethod I am able to do what I want. But I keep thinking this is wrong because now if I do container.ResolveAll() I'd really like it to skip the factory method but I don't know how to make it do that.
Why not just create a custom component type selector and decide which component to load based on that?
Typed Factory Facility - interface-based factories