IAutoMappingOverride.Override not being called - c#

I can't seem to get the FluentNHibernate overrides to run. Here's my configuration method
private static void Configure()
{
if (_configuration != null) return;
_configuration = new Configuration();
_configuration.Configure();
_configuration
.AddAssembly(typeof(IFoo).Assembly)
.AddAssembly(OtherDataAssembly);
var autoPersistenceModel = AutoMap
.AssemblyOf<IFoo>()
.AddEntityAssembly(OtherDataAssembly)
.Conventions.AddAssembly(OtherDataAssembly)
.Conventions.Add(DefaultCascade.None())
.UseOverridesFromAssemblyOf<IFoo>()
.UseOverridesFromAssembly(OtherDataAssembly)
.OverrideAll(map => map.IgnoreProperty("IsIgnored"))
.Where(IsTypeMatch);
_sessionFactory = Fluently
.Configure(Configuration)
.Mappings(m => m.AutoMappings
.Add(autoPersistenceModel))
.BuildSessionFactory();
}
Here's my override class
public class FooOverride : IAutoMappingOverride<IFoo>
{
public void Override(AutoMapping<IFoo> mapping)
{
mapping.Not.LazyLoad();
mapping.HasManyToMany(x => x.Bar).Table("FooBar");
}
}
Breakpoints I put in the Override() method are never hit when debugging, even when restarting IIS. How do I get this to run?

Overrides are only run on the exact same class, not classes which are assignable to the class in the generic type parameter of IAutoMappingOverride.
Update:
The only other options i can think of now are:
let FooOverride implement several IAuotMappingOverride<> for each class implementing IFoo
add the overides yourself using Reflection. untestet:
var overrideMethod = typeof(AutoPersistenceModel).GetMethod("Override");
foreach (var type in typeof(IFoo).Assembly)
{
if (typeof(IFoo).IsAssignableFrom(type))
{
overrideMethod.MakeGenericMethod(type).Invoke(new Action<IFoo>(m => m.HasMayToMany(...)));
}
}

Related

Do I need dependency injection to automatically register my message handlers?

I have RegisterMessageHandlers that register message handler per message name.
I want to automatically find and register all handlers through reflection. I can annotate each message with MessageAttribute (like shown below) and get the message name through reflection as well. The problem is when I want to instantiate a handler via Activator I have to provide all the dependencies in the constructor.
My solution is to register all instances with DI and pass IServiceProvider to MainManagerClass(IServiceProvider provider) and then use ActivatorUtilities.CreateInstance(handlerType) to instantiate each discovered handler through reflection.
But, then I read that there is DI and service locator which is antipattern and it's not very clear when one becomes the other.
So, I think I need a DI in order to accomplish what I want. Or do I?
public class MainManagerClass
{
private Dictionary<string, MessageHandler> _handlers;
private void RegisterMessageHandlers()
{
_messageHandlers["msg1"] = new MessageHandler1(new Service1());
_messageHandlers["msg2"] = new MessageHandler2(new Service1(), new Service2());
}
}
public class MessageHandler1 : MessageHandler<Message1>
{
public MessageHandler1(IService1 service){}
}
public class MessageHandler2 : MessageHandler<Message2>
{
public MessageHandler1(IService1 service1, IService2 service2){}
}
public abstract class MessageHandler<T> : MessageHandler
{
}
public abstract class MessageHandler
{
}
[Message("msg1")]
public class Message1
{
}
UPDATE
public class MainManagerClass
{
private Dictionary<string, MessageHandler> _handlers;
private readonly IServiceProvider _serviceProvider;
public MainManagerClass(IServiceProvider serviceProvider)
{
}
private void RegisterMessageHandlers()
{
var messageHandlers = Assembly.GetCallingAssembly()
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(MessageHandler))).ToList();
foreach (var handler in messageHandlers)
{
var messageType = handler.BaseType.GenericTypeArguments[0];
var msgAttribute = messageType.CustomAttributes
.Where(t => t.AttributeType == typeof(MessageAttribute))
.FirstOrDefault();
if (msgAttribute == null)
throw new Exception($"Message name not defined for message type {messageType.Name}");
var msgName = msgAttribute.ConstructorArguments[0].Value.ToString();
_messageHandlers[msgName] = ActivatorUtilities.CreateInstance(_serviceProvider, handler) as MessageHandler;
}
}
}
internal class Program
{
static async Task Main(string[] args)
{
var host = CreateHostBuilder().Build();
var manager = new MainManagerClass(host.Services);
...
}
private static IHostBuilder CreateHostBuilder()
{
return Host.CreateDefaultBuilder()
.ConfigureServices((_, services) =>
{
services
.AddSingleton<IService1, Service1>()
.AddSingleton<IService2, Service2>()
.AddSingleton<IService3, Service3>()
;
});
}
}
If you don't want to add interface and keep abstract class as in your example - you can register your handlers like that:
builder.Services.AddTransient<MessageHandler<Message1>, MessageHandler1>();
builder.Services.AddTransient<MessageHandler<Message2>, MessageHandler2>();
And then if you inject MessageHandler<Message1> in your controller for instance, MessageHandler1 will be resolved as well as other dependencies (IService1 in your case).
I think I still don't get your question but I hope this will be helpfull for you. Anyway, I followed Jaroslav's answer and your comment to create MessageHandlerFactory object then I changed your code a bit to cover both scenarios but you need the message type to resolve its handler from the service provider plus, If you want to register all handlers automatically, you should use reflection at startup, find all objects that inherit from IMessageHandler<T>, and register them to DI or use packages like Scrutor.
public class MessageHandlerFactory
{
private IServiceProvider _serviceProvider;
public IMessageHandler<T> ResolveHandler<T>()
{
return _serviceProvider.GetRequiredService<IMessageHandler<T>>();
}
}
public class MessageHandler1 : IMessageHandler<Message1>
{
public MessageHandler1(IService1 service){}
}
public class MessageHandler2 : IMessageHandler<Message2>
{
public MessageHandler2(IService1 service1, IService2 service2){}
}
public interface IMessageHandler<T>
{
}
public class Message1
{
}
public class Message2
{
}
builder.Services.AddScoped<IMessageHandler<Message1>, MessageHandler1>();
builder.Services.AddScoped<IMessageHandler<Message2>, MessageHandler2>();

How can I setup StaticResourceExtension when unit testing a markup extension that relies on it?

I have written a custom markup extension : CoalesceResourceExtension
[MarkupExtensionReturnType(typeof(object))]
public class CoalesceResourceExtension : MarkupExtension
{
public CoalesceResourceExtension(string resources)
{
this.Resources = resources;
}
public string Separator { get; set; }
[ConstructorArgument("resources")]
public string Resources { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Resources != null)
{
foreach (string resourceName in Resources.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries))
{
try
{
if (new StaticResourceExtension(resourceName).ProvideValue(serviceProvider) is object resource)
{
return resource;
}
}
catch { }
}
}
return null;
}
}
But when I come to unit testing CoalesceResourceExtension, I can't seem to find a way to setup the StaticResourceExtension so that it will find the desired mocked resources. Is there a way I can setup things for the StaticResourceExtension to find my mocked resources?
StaticResourceExtension.ProvideValue(IServiceProvider)'s behaviour can be controlled via mocking the IServiceProvider passed by CoalesceResourceExtension to the StaticResourceExtension but you'll also need to mock all the services and objects from the services it uses : IAmbientProvider, IXamlSchemaContextProvider, XamlSchemaContext, ResourceDictionary, XamlType, PropertyInfo and XamlMember. I've built these mocks by watching what path the StaticResourceExtension was taking by both making the mocks strict and watching the exceptions they were throwing when meeting a member that wasn't setup and by looking at StaticResourceExtension's source code.
Here's a method that builds the whole mocked IServiceProvider for every needed key + value pair passed in :
private IServiceProvider MockIServiceProviderForStaticResourceExtension(params KeyValuePair<object, object>[] resources)
{
Mock<IServiceProvider> serviceProviderMock = new Mock<IServiceProvider>(MockBehavior.Strict);
Mock<IXamlSchemaContextProvider> xamlSchemaContextProviderMock = new Mock<IXamlSchemaContextProvider>(MockBehavior.Strict);
Mock<IAmbientProvider> ambientProviderMock = new Mock<IAmbientProvider>(MockBehavior.Strict);
Mock<XamlSchemaContext> xamlSchemaContextMock = new Mock<XamlSchemaContext>(MockBehavior.Strict);
xamlSchemaContextMock.Setup(xsc => xsc.GetXamlType(It.IsAny<Type>())).Returns((Func<Type, XamlType>)(t => GetXamlTypeForType(t, xamlSchemaContextMock.Object)));
ambientProviderMock.Setup(ap => ap.GetAllAmbientValues(null, false, It.IsAny<IEnumerable<XamlType>>(), It.IsAny<XamlMember[]>())).Returns((Func<IEnumerable<XamlType>, bool, IEnumerable<XamlType>, XamlMember[], IEnumerable<AmbientPropertyValue>>)GetAllAmbientValuesImplementation);
xamlSchemaContextProviderMock.Setup(xscp => xscp.SchemaContext).Returns(xamlSchemaContextMock.Object);
serviceProviderMock.Setup(s => s.GetService(typeof(IXamlSchemaContextProvider))).Returns(xamlSchemaContextProviderMock.Object);
serviceProviderMock.Setup(s => s.GetService(typeof(IAmbientProvider))).Returns(ambientProviderMock.Object);
serviceProviderMock.Setup(s => s.GetService(It.IsNotIn(typeof(IXamlSchemaContextProvider), typeof(IAmbientProvider)))).Returns(null);
return serviceProviderMock.Object;
IEnumerable<AmbientPropertyValue> GetAllAmbientValuesImplementation(IEnumerable<XamlType> ceilingTypes, bool searchLiveStackOnly, IEnumerable<XamlType> types, params XamlMember[] properties)
{
Mock<ResourceDictionary> resourceDictionaryMock = new Mock<ResourceDictionary>(MockBehavior.Strict);
resourceDictionaryMock.Protected().Setup("OnGettingValue", false, ItExpr.Is<object>(o => resources.Any(kvp => kvp.Key.Equals(o))), ItExpr.Ref<object>.IsAny, ItExpr.Ref<bool>.IsAny).CallBase();
foreach (KeyValuePair<object, object> kvp in resources)
{
resourceDictionaryMock.Object.Add(kvp.Key, kvp.Value);
}
Mock<AmbientPropertyValue> ambientPropertyValueMock = new Mock<AmbientPropertyValue>(MockBehavior.Strict, null, resourceDictionaryMock.Object);
return new List<AmbientPropertyValue> { ambientPropertyValueMock.Object };
}
XamlType GetXamlTypeForType(Type t, XamlSchemaContext xamlSchemaContext)
{
Mock<XamlType> xamlTypeMock = new Mock<XamlType>(MockBehavior.Strict, t, xamlSchemaContext);
xamlTypeMock.Protected().Setup<XamlMember>("LookupMember", true, "Resources", false).Returns((Func<string, bool, XamlMember>)LookupMemberImplementation);
xamlTypeMock.Protected().Setup<XamlMember>("LookupMember", true, "BasedOn", false).Returns((Func<string, bool, XamlMember>)LookupMemberImplementation);
xamlTypeMock.Setup(xt => xt.ToString()).CallBase();
return xamlTypeMock.Object;
XamlMember LookupMemberImplementation(string name, bool skipReadOnlyCheck)
{
Mock<PropertyInfo> propertyInfoMock = new Mock<PropertyInfo>(MockBehavior.Strict);
propertyInfoMock.Setup(pi => pi.Name).Returns(name);
propertyInfoMock.Setup(pi => pi.DeclaringType).Returns(t);
Mock<XamlMember> xamlMemberMock = new Mock<XamlMember>(MockBehavior.Strict, propertyInfoMock.Object, xamlSchemaContext);
xamlMemberMock.Setup(xm => xm.ToString()).CallBase();
return xamlMemberMock.Object;
}
}
}
I ran into a similar issue with a ValueConverter/MarkupExtension that was using Application.Current.TryFindResource().
I created an interface called IApplicationResourceResolver with a method definition for TryFindResource.
Then I created an implementation of the interface called ApplicationResourceResolver that uses Application.Current.TryFindResource().
In my converter/extension I have a public property:
public IApplicationResourceResolver Resolver {get; internal set; }
And in my constructor, I setup my default implementation:
public StringToResourceConverter()
{
Resolver = new ApplicationResourceResolver();
}
Now, in my unit tests, I can set Resolver to a mocked up version to do tests!
You should be able to use this pattern to solve your issue. I hope this helps.

Instantiating types using AutoMapper with a DI container

Please see the code below:
public class Test : ITest
{
public ITest2 _iTest2;
public int _id;
public string _name;
public Test(ITest2 test2)
{
_iTest2 = test2;
}
}
public interface ITest
{
}
public class Test2 : ITest2
{
}
public interface ITest2
{
}
public class Test3 : ITest3
{
public int _id;
public string _name;
}
public interface ITest3
{
}
I have the following in my Global.asax:
Mapper.Initialize(m =>
{
m.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
});
I can map the types in my client app doing this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
How can I map the types using Castle Windsor instead of having to use the new keyword for Test and Test2?
I read another answer and someone suggested doing this:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn(typeof(IValueResolver<,,>)));
// container.Register(Types.FromAssembly(Assembly.GetExecutingAssembly()).BasedOn<IValueResolver>());
container.Register(Types.FromThisAssembly().BasedOn<Profile>().WithServiceBase());
var profiles = container.ResolveAll<Profile>();
// Add your list of profiles to the mapper configuration here
Mapper.Initialize(m => {
m.ConstructServicesUsing(container.Resolve);
profiles.ToList().ForEach(p => m.AddProfile(p));
});
// I'm not sure about this as I haven't used AutoMapper for a while,
// but I assume you want to resolve the static mapper instance
container.Register(Component.For<IMapper>().Instance(Mapper.Instance));
}
Do I have to do this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>().ConstructUsing(opt => new BusinessLayer.Test(new BusinessLayer.Test2()));
or should AutoMapper be able to map the types using this:
cfg.CreateMap<DataLayer.Test3, BusinessLayer.Test>()
In order to get AutoMapper to use Windsor to create the target type, you need to configure two things:
Tell AutoMapper to construct services using Windsor
Tell AutoMapper (per-mapping) to actually use the above configuration
var container = new WindsorContainer();
Mapper.Initialize(m =>
{
m.ConstructServicesUsing(container.Resolve);
m.CreateMap<Test3, ITest>().ConstructUsingServiceLocator(); // This is important!
});
container.Register(Component.For<ITest>().ImplementedBy<Test>());
container.Register(Component.For<ITest2>().ImplementedBy<Test2>());
container.Register(Component.For<ITest3>().ImplementedBy<Test3>());
var test3 = new Test3();
var test1 = Mapper.Instance.Map<Test3, ITest>(test3);
For anyone requiring this using xamarin 3.6, prism 7.1 and automapper 8.1, this is what worked for me.
In the App.xml.cs file
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
/// other registrations ...
containerRegistry.RegisterSingleton<IMapperProvider, MapperProvider>();
containerRegistry.RegisterInstance(typeof(IMapper), GetMapper(containerRegistry));
}
/// <summary>
/// This function required in order for injection into custom automapper resolvers
/// </summary>
private IMapper GetMapper(IContainerRegistry container)
{
var mp = container.GetContainer().Resolve<IMapperProvider>(new[] { container });
return mp.GetMapper();
}
The mapper provider looks like this:
public class MapperProvider : IMapperProvider
{
private readonly IContainerRegistry _container;
public MapperProvider(IContainerRegistry container)
{
_container = container;
}
public IMapper GetMapper()
{
var config = new MapperConfiguration(cfg =>
{
cfg.ConstructServicesUsing(t => _container.GetContainer().Resolve(t));
// any custom profile statement such as
cfg.AddProfile<MappingSourcesProfile>();
// ....
});
return config.CreateMapper();
}
}
Now my custom resolvers works, for example:
public class BarcodesResolver : IValueResolver<repo.Book, Book, List<Barcode>>
{
private readonly IMapper _mapper;
public BarcodesResolver(IMapper mapper)
{
_mapper = mapper;
}
public List<Barcode> Resolve(repo.Book source, Book destination, List<Barcode> destMember, ResolutionContext context)
{
repo.BookAttributes groupedAttribs = JsonConvert.DeserializeObject<repo.BookAttributes>(source.BookAttributes);
return _mapper.Map<List<repo.Barcode>, List<Barcode>>(groupedAttribs.Barcodes);
}
}
The hard parts to work out here were how to specify that the containerRegistry needed to be passed into the constructor of the MapperProvider. There may be a better way of doing this but at least this works.
Also arriving at the line cfg.ConstructServicesUsing(t => _container.GetContainer().Resolve(t)); was quite obscure as there seem to be few examples out there.

How do I set up dependency injection if my concrete class requires simple data type in addition to other interface(s)?

If I have a class structure like below:
public interface IDataProvider
{
object GetSomeData(int id);
}
public class InMemoryDataProvider : IDataProvider
{
public InMemoryDataProvider(string connString)
{
}
public object GetSomeData(int id)
{
return new object();
}
}
public interface IAnimal
{
string GetName();
}
public class Dog: IAnimal
{
public Dog(string someRequiredInfo, IDataProvider someDataProvider)
{
}
public string GetName()
{
return string.Empty;
}
}
I am trying to set up DI chain using default DI container that comes with asp.net core MVC. But I don't understand how to set up for my scenario. I am new to using DI container so I could be missing some fundamental idea.Below is how I tried to set it up (unsuccessfully):
string connString = "connectionString";
someString = "some required info";
AddSingleton<IDataProvider, InMemoryDataProvider>(x => new InMemoryDataProvider(connString));
AddTransient<IAnimal, Dog>(); //if I do this, how will it get the first parameter of someString? Don't think this will even work.
AddTransient<IAnimal, Dog>(x => new Dog(someString, IDataProvider???)) //how to do this?
Also, I want the data provider to be a singleton and that eliminates the possibility of doing like below isn't it?
services.AddTransient<IAnimal, Dog>(x => new Dog(someString, new InMemoryDataProvider(connString)));
You need to change your code in yout Startup.cs to the snippet below.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddSingleton(x => new InMemoryDataProvider(connString));
services.AddSingleton<IDataProvider, InMemoryDataProvider>(x => x.GetService<InMemoryDataProvider>());
services.AddSingleton<IAnimal, Dog>(d=> new Dog(someString, d.GetService<IDataProvider>()));
services.AddMvc();
}
And just inject IAnimal into your Controllers constructor like so:
public ValuesController(IAnimal animal)
{
_animal = animal;
}

Unity to Structure Map

I am trying out the code from this post on Event Driven Architecture (very interesting by the way). His IOC container is Unity though and I would like to do this using Structure map.
His code is:
public class EventSubscriptions : ISubscriptionService
{
public static void Add<T>()
{
var consumerType = typeof(T);
consumerType.GetInterfaces()
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == typeof(IConsumer<>))
.ToList()
.ForEach(x => IoC.Container.RegisterType(x,
consumerType,
consumerType.FullName));
}
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = IoC.Container.ResolveAll(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
I have the following which does not seem to be working:
public class SubscriptionService : ISubscriptionService
{
public static void Add<T>()
{
var consumerType = typeof(T);
consumerType.GetInterfaces()
.Where(x => x.IsGenericType)
.Where(x => x.GetGenericTypeDefinition() == typeof (IConsumer<>))
.ToList().ForEach(x => ObjectFactory.Inject(consumerType, x));
}
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = ObjectFactory.GetAllInstances(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
I am obviously not too familiar with Structure Map. Some links or explanation on what I am doing wrong would be really appreciated.
Update:
From Henning's answer, I ended up with -
public class SubscriptionService : ISubscriptionService
{
public IEnumerable<IConsumer<T>> GetSubscriptions<T>()
{
var consumers = ObjectFactory.GetAllInstances(typeof(IConsumer<T>));
return consumers.Cast<IConsumer<T>>();
}
}
And then in my bootstrapping class that is called on application startup I have:
public static void ConfigureStuctureMap()
{
ObjectFactory.Initialize(x =>
{
x.Scan(y =>
{
y.Assembly("Domain");
y.Assembly("Website");
y.AddAllTypesOf(typeof(IConsumer<>));
y.WithDefaultConventions();
});
});
}
Although I'm not a structuremap expert, I do believe you can do it in another way.
Structuremap has the ability to scan any given assembly for a given interface and automatically register all the implementations. We do that in my current project and it works really great.
I don't remember the exact code we use, but you can check out the documentation for assembly scanning
http://structuremap.sourceforge.net/ScanningAssemblies.htm
Build custom TypeScanner class that implement ITypeScanner interface.
public class EventSubConventionScanner : ITypeScanner
{
public void Process(Type type, PluginGraph graph)
{
Type interfaceType = type.FindInterfaceThatCloses(typeof(IConsumer<>));
if (interfaceType != null)
{
graph.AddType(interfaceType, type);
}
}
}
After, in registry or initialize routine write:
Scan(x =>
{
x.With<EventSubConventionScanner>();
});

Categories

Resources