How do I bind an Interface to automapper using Ninject - ninject

I want to use DI whenever I call automapper so that I can uncouple some of my layers. Instead of calling automapper like this:
public class MyController : Controller
{
public ActionResult MyAction(MyModel model)
{
var newModel= Mapper.Map<MyModel, NewModel>(model);
return View(model);
}
}
I want to do this:
public class MyController : Controller
{
IMappingEngine _mappingEngine;
public MyController(IMappingEngine mappingEngine)
{
_mappingEngine = mappingEngine;
}
public ActionResult MyAction(MyModel model)
{
var newModel= _mappingEngine.Map<MyModel, NewModel>(model);
return View(model);
}
}
I am using Ninject as my IOC. How do I bind an interface to it though?
I also need to mention that I am using Profiles and already have:
var profileType = typeof(Profile);
// Get an instance of each Profile in the executing assembly.
var profiles = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => profileType.IsAssignableFrom(t)
&& t.GetConstructor(Type.EmptyTypes) != null)
.Select(Activator.CreateInstance)
.Cast<Profile>();
// Initialize AutoMapper with each instance of the profiles found.
Mapper.Initialize(a => profiles.ForEach(a.AddProfile));
I know that the step I am missing involves binding to the kernal:
kernel.Bind<IMappingEngine>.To<>(); //I do not know what
//to bind it to here so that when I call IMappingEngine;
//It will trigger my maps from my automapper profiles.

I can't seem to find IMappingService in the AutoMapper repository (https://github.com/AutoMapper/AutoMapper/search?q=IMappingService). However, there is a IMappingEngine.
All you've got to do is
IBindingRoot.Bind<IMappingEngine>().ToMethod(x => Mapper.Engine);
or
IBindingRoot.Bind<IMappingEngine>().To<MappingEngine>();
IBindingRoot.Bind<IConfigurationProvider>().ToMethod(x => Mapper.Engine.ConfigurationProvider);
and you're good to go.
Remember, however, that the first access to Mapper.Engine or Mapper.ConfigurationProvider will initialize AutoMapper.
So without the binding, AutoMapper get's initialized the first time you do something like Mapper.Map<,>. With the binding it will get initialized the first time an object is constructed which gets IMappingEngine injected.
If you want to retain the previous initialization behavior there are a few choices:.
a) Instead of injecting IMappingEngine inject Lazy<IMappingEngine> instead (i think this requires the ninject.extensions.factory extension)
b) bind IMappingEngine to a proxy (without target). The proxy should access the Mapper.Engine only when .Intercept(...)ing a method. Also it should forward the method calls.
c) write your own LazyInitializedMappingEngine : IMappingEngine implementation which does nothing than forward every method to Mapper.Engine.
i would probably go with c), the others are too much work. c) will require code adaption whenever the interface of IMappingEngine changes. b) would not but is more complicated and slower. a) is bleeding through to all consumers of the interface and easily to get wrong once in a while, breaking stuff and a bit hard to trace back, so i would refrain from it, too.
c):
public class LazyInitializedMappingEngine : IMappingEngine
{
public IConfigurationProvider ConfigurationProvider { get { return Mapper.Engine.ConfigurationProvider; } }
public TDestination Map<TDestination>(object source)
{
return Mapper.Map<TDestination>(source);
}
public TDestination Map<TDestination>(object source, Action<IMappingOperationOptions> opts)
{
return Mapper.Map<TDestination>(source, opts);
}
public TDestination Map<TSource, TDestination>(TSource source)
{
return Mapper.Map<TSource, TDestination>(source);
}
//... and so on ...
}
kernel.Bind<IMappingEngine>().To<LazyInitializedMappingEngine>();

Related

How to force MOXy to use the setter on a Collection property that is lazily initialized?

Given a bean like this:
public class MyBean {
private List<Something> things;
private List<Something> internalGetThings() {
if (things == null) {
things = new ArrayList<Something>();
}
return things;
}
public Iterable<Something> getThings() {
return <an immutable copy of internalGetThings()>;
}
public void setThings(List<Something> someThings) {
things.clear();
for (Something aThing : someThings) {
addThing(aThing);
}
}
public void addThing(Something aThing) {
things.add(aThing);
// Do some special stuff to aThing
}
}
Using external mapping file, when I map like this:
<xml-element java-attribute="things" name="thing" type="com.myco.Something" container-type="java.util.ArrayList" />
It seems that each individual Something is being added to the MyBean by calling getThings().add(). That's a problem because getThings() returns an immutable copy of the list, which is lazily initialized. How can I configure mapping (I'm using an external mapping file, not annotations) so that MOXy uses setThings() or addThing() instead?
Why Does JAXB/MOXy Check the Get Method for Collection First?
JAXB (JSR-222) implementations give you a chance to have your property be the List interface and still leverage the underlying List implementation that you choose to use. To accomplish this a JAXB implementation will call the get method to see if the List implementation has been initialized. It it has the List will be populated using the add method.
public List<String> getThings() {
if(null == things) {
things = new ArrayList<String>();
}
return things;
}
public List<String> getThings() {
if(null == things) {
things = new LinkedList<String>();
}
return things;
}
If you don't pre-initialize the List property then MOXy/JAXB will build an instance of the List (default is ArrayList) and set it on the object using the set method.
private List<Something> things; // Don't Initialize
public List<String> getThings() {
return things;
}
public void setThings(List<String> things) {
this.things = things;
}
Given the reason in #Blaise's answer, it doesn't seem possible to have MOXy (or any JAXB implementation in general?) populate a lazily-initialized collection via a setter method on the collection. However, a combination of xml-accessor-type="FIELD" (or #XmlAccessorType if using annotations) and defining a JAXB unmarshal event callback will get the job done. In my afterUnmarshal() implementation I do the special work on Something instances that is done in addSomething().
private void afterUnmarshal(Unmarshaller, Object parent) {
for (Something aThing : getSomethings()) {
// Do special stuff on aThing
}
}
Using FIELD access type gets JAXB/MOXy to directly inject the collection into the field, bypassing the getter. Then the call back cleans things up properly.

Can I Use Ninject To Bind A Boolean Value To A Named Constructor Value

I have a constructor such as:
public AnalyticsController(ClassA classA, ClassB classB, bool isLiveEnvironment)
{
...
}
isLiveEnvironment is determined using a call to an existing static class such as:
MultiTenancyDetection.GetInstance().IsLive();
I would like to be able to make this call outside of the controller and inject the result into isLiveEnvironment. Is this possible? I can not see how this can be done.
You can accomplish this using WithConstructorArgument and using a callback:
kernel.Bind<AnalyticsController>()
.ToSelf()
.WithConstructorArgument("isLiveEnvironment", ctx => MultiTenancyDetection.GetInstance().IsLive() );
You can even achieve this more generally (but i would not really recommend binding such a generic type for such a specific use case):
IBindingRoot.Bind<bool>().ToMethod(x => MultiTenancyDetection.GetInstance().IsLive())
.When(x => x.Target.Name == "isLiveEnvironment");
Alternatively, if you need the same configuration value in several / a lot of classes, create an interface for it:
public interface IEnvironment
{
bool IsLive { get; }
}
internal class Environment : IEnvironment
{
public bool IsLive
{
get
{
return MultiTenancyDetection.GetInstance().IsLive();
}
}
}
IBindingRoot.Bind<IEnvironment>().To<Environment>();

jmockit - Mocking chain of methods one of which returns a Collection using #Cascading

I am trying to mock a method call which goes something like this:
rapContext.getSysInfo().get(key)
The getSysInfo() method returns a ConcurrentHashMap.
Here is what I have done:
Class ABCTest {
#Cascading RapContext context;
#Test
doTest() {
new Expectations() {
{
rapContext.getSysInfo().get(anyString);
result = new UserPrefCtxObject();
}
}
}
With this I get a NullPointerException on rapContext.getSysInfo(). Call to getSysInfo() returns null. If I call any other method which does not return a collection, for instance rapContext.getDomain() everything working fine.
I am not sure what I am missing.
Thanks
The code example is not complete however you are likely running into some issue associated with accidentally mocking Map. If a Map (or any part of the Collection framework) is mocked then a lot of things will break. I could not reproduce your problem as any attempt to mock RapContext using #Cascading resulted in a stack over flow.
You could partially mock RapContext instead and then either return a real or mocked Map. When I run into similar issues I generally get around them using either #Injectable to only mock an instance of a class or using partial mocks.
Here is an approach that will let you mock getSysInfo:
public class RapContextTest {
#Injectable ConcurrentHashMap<String, Object> mockedMap;
#Test
public void testContext() {
RapContext context = new RapContext();
new MockUp<RapContext>(){
#Mock
public ConcurrentHashMap getSysInfo(){
return mockedMap;
}
};
new NonStrictExpectations() {
{
mockedMap.get(anyString);
result = "Success";
}
};
Object value = context.getSysInfo().get("test");
System.out.println(value);
}
}

DbContext API Ignore for each entity

I’m trying to use CodeFirst EF. The issue is it's loading 50+ tables for each domain context (DbContext). The ignore is working if I pass the strong name class so the compiler knows what it is but it will be too hard to hardcode all the ignores.
Is there a way to loop through all the classes in a referenced DLL and pass that to the ignore? I have code that is close (taking code from post) but I can’t figure out a way to pass the class type with Assembly information. I’m so close yet so far away…
Assembly pocoQMAssembly = AssemblyInformationPOCO_QM.Get;
foreach (Type typeInfo in pocoQMAssembly.GetTypes())
{
//Make sure it is not one of the classes used in DbSet<>
if (typeInfo != typeof(tbl_age_groups) ||
typeInfo != typeof(tbl_axis)
)
{
//This line will show an error on typeInfo
//Is there a way to cast it to a class in some way so it likes it?
modelBuilder.Ignore<typeInfo>();
}
}
This will expose the Assembly to get it easily.
public class AssemblyInformationPOCO_QM
{
public static System.Reflection.Assembly Get
{
get
{
return typeof(AssemblyInformationPOCO_QM).Assembly;
}
}
}
Here is some code that does what you are after. It finds all types that are explicitly included in a DbSet property, it then uses this to find all types in your model assembly that aren't in a DbSet, and then calls Ignore on them.
public class MyContext : DbContext
{
// DbSet properties go here
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var dbSetTypes = this.GetType()
.GetProperties()
.Where(p => p.PropertyType.Name == "DbSet`1")
.Select(s => s.PropertyType.GenericTypeArguments.Single());
var nonDbSetTypes = typeof(MyEntityClass).Assembly // <- replace MyEntityClass with one of your types
.GetTypes()
.Except(dbSetTypes);
modelBuilder.Ignore(nonDbSetTypes);
}
}

JSON.NET and nHibernate Lazy Loading of Collections

Is anybody using JSON.NET with nHibernate? I notice that I am getting errors when I try to load a class with child collections.
I was facing the same problem so I tried to use #Liedman's code but the GetSerializableMembers() was never get called for the proxied reference.
I found another method to override:
public class NHibernateContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType))
return base.CreateContract(objectType.BaseType);
else
return base.CreateContract(objectType);
}
}
We had this exact problem, which was solved with inspiration from Handcraftsman's response here.
The problem arises from JSON.NET being confused about how to serialize NHibernate's proxy classes. Solution: serialize the proxy instances like their base class.
A simplified version of Handcraftsman's code goes like this:
public class NHibernateContractResolver : DefaultContractResolver {
protected override List<MemberInfo> GetSerializableMembers(Type objectType) {
if (typeof(INHibernateProxy).IsAssignableFrom(objectType)) {
return base.GetSerializableMembers(objectType.BaseType);
} else {
return base.GetSerializableMembers(objectType);
}
}
}
IMHO, this code has the advantage of still relying on JSON.NET's default behaviour regarding custom attributes, etc. (and the code is a lot shorter!).
It is used like this
var serializer = new JsonSerializer{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new NHibernateContractResolver()
};
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter);
serializer.Serialize(jsonWriter, objectToSerialize);
string serializedObject = stringWriter.ToString();
Note: This code was written for and used with NHibernate 2.1. As some commenters have pointed out, it doesn't work out of the box with later versions of NHibernate, you will have to make some adjustments. I will try to update the code if I ever have to do it with later versions of NHibernate.
I use NHibernate with Json.NET and noticed that I was getting inexplicable "__interceptors" properties in my serialized objects. A google search turned up this excellent solution by Lee Henson which I adapted to work with Json.NET 3.5 Release 5 as follows.
public class NHibernateContractResolver : DefaultContractResolver
{
private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers();
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo =>
(IsMemberPartOfNHibernateProxyInterface(memberInfo)) ||
(IsMemberDynamicProxyMixin(memberInfo)) ||
(IsMemberMarkedWithIgnoreAttribute(memberInfo, objectType)) ||
(IsMemberInheritedFromProxySuperclass(memberInfo, objectType)));
var actualMemberInfos = new List<MemberInfo>();
foreach (var memberInfo in members)
{
var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name);
actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]);
}
return actualMemberInfos;
}
private static bool IsMemberDynamicProxyMixin(MemberInfo memberInfo)
{
return memberInfo.Name == "__interceptors";
}
private static bool IsMemberInheritedFromProxySuperclass(MemberInfo memberInfo, Type objectType)
{
return memberInfo.DeclaringType.Assembly == typeof(INHibernateProxy).Assembly;
}
private static bool IsMemberMarkedWithIgnoreAttribute(MemberInfo memberInfo, Type objectType)
{
var infos = typeof(INHibernateProxy).IsAssignableFrom(objectType)
? objectType.BaseType.GetMember(memberInfo.Name)
: objectType.GetMember(memberInfo.Name);
return infos[0].GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length > 0;
}
private static bool IsMemberPartOfNHibernateProxyInterface(MemberInfo memberInfo)
{
return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name);
}
}
To use it just put an instance in the ContractResolver property of your JsonSerializer. The circular dependency problem noted by jishi can be resolved by setting the ReferenceLoopHandling property to ReferenceLoopHandling.Ignore . Here's an extension method that can be used to serialize objects using Json.Net
public static void SerializeToJsonFile<T>(this T itemToSerialize, string filePath)
{
using (StreamWriter streamWriter = new StreamWriter(filePath))
{
using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
{
jsonWriter.Formatting = Formatting.Indented;
JsonSerializer serializer = new JsonSerializer
{
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new NHibernateContractResolver(),
};
serializer.Serialize(jsonWriter, itemToSerialize);
}
}
}
Are you getting a circular dependancy-error? How do you ignore objects from serialization?
Since lazy loading generates a proxy-objects, any attributes your class-members have will be lost. I ran into the same issue with Newtonsoft JSON-serializer, since the proxy-object didn't have the [JsonIgnore] attributes anymore.
You will probably want to eager load most of the object so that it can be serialized:
ICriteria ic = _session.CreateCriteria(typeof(Person));
ic.Add(Restrictions.Eq("Id", id));
if (fetchEager)
{
ic.SetFetchMode("Person", FetchMode.Eager);
}
A nice way to do this is to add a bool to the constructor (bool isFetchEager) of your data provider method.
I'd say this is a design problem in my opinion. Because NH makes connections to the database underneath all and has proxies in the middle, it is not good for the transparency of your application to serialize them directly (and as you can see Json.NET does not like them at all).
You should not serialize the entities themselves, but you should convert them into "view" objects or POCO or DTO objects (whatever you want to call them) and then serialize these.
The difference is that while NH entity may have proxies, lazy attributes, etc. View objects are simple objects with only primitives which are serializable by default.
How to manage FKs?
My personal rule is:
Entity level: Person class and with a Gender class associated
View level: Person view with GenderId and GenderName properties.
This means that you need to expand your properties into primitives when converting to view objects. This way also your json objects are simpler and easier to handle.
When you need to push the changes to the DB, in my case I use AutoMapper and do a ValueResolver class which can convert your new Guid to the Gender object.
UPDATE: Check http://blog.andrewawhitaker.com/blog/2014/06/19/queryover-series-part-4-transforming/ for a way to get the view directly (AliasToBean) from NH. This would be a boost in the DB side.
The problem can happen when NHibernate wraps the nested collection properties in a PersistentGenericBag<> type.
The GetSerializableMembers and CreateContract overrides cannot detect that these nested collection properties are "proxied". One way to resolve this is to override the CreateProperty method. The trick is to get the value from the property using reflection and test whether the type is of PersistentGenericBag. This method also has the ability to filter any properties that generated exceptions.
public class NHibernateContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = instance =>
{
try
{
PropertyInfo prop = (PropertyInfo)member;
if (prop.CanRead)
{
var value = prop.GetValue(instance, null);
if (value != null && typeof(NHibernate.Collection.Generic.PersistentGenericBag<>).IsSubclassOfRawGeneric(value.GetType()))
return false;
return true;
}
}
catch
{ }
return false;
};
return property;
}
}
The IsSubclassOfRawGeneric extension used above:
public static class TypeExtensions
{
public static bool IsSubclassOfRawGeneric(this Type generic, Type? toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck?.BaseType;
}
return false;
}
}
If you serialize objects that contain NHibernate proxy classes you might end up downloading the whole database, because once the property is accessed NHibernate would trigger a request to the database.
I've just implemented a Unit of Work for NHibernate: NHUnit that fixes two of the most annoying issues from NHibernate: proxy classes and cartesian product when using fetch.
How would you use this?
var customer = await _dbContext.Customers.Get(customerId) //returns a wrapper to configure the query
.Include(c => c.Addresses.Single().Country, //include Addresses and Country
c => c.PhoneNumbers.Single().PhoneNumberType) //include all PhoneNumbers with PhoneNumberType
.Unproxy() //instructs the framework to strip all the proxy classes when the Value is returned
.Deferred() //instructs the framework to delay execution (future)
.ValueAsync(token); //this is where all deferred queries get executed
The above code is basically configuring a query: return a customer by id with multiple child objects which should be executed with other queries (futures) and the returned result should be stripped of NHibernate proxies. The query gets executed when ValueAsync is called.
NHUnit determines if it should do join with the main query, create new future queries or make use of batch fetch.
There is a simple example project on Github to show you how to use NHUnit package. If others are interested in this project I will invest more time to make it better.
This is what I use:
Have a marker interface and inherit it on your entities, e.g. in my case empty IEntity.
We will use the marker interface to detect NHibernate entity types in the contract resolver.
public class CustomerEntity : IEntity { ... }
Create a custom contract resolver for JSON.NET
public class NHibernateProxyJsonValueProvider : IValueProvider {
private readonly IValueProvider _valueProvider;
public NHibernateProxyJsonValueProvider(IValueProvider valueProvider)
{
_valueProvider = valueProvider;
}
public void SetValue(object target, object value)
{
_valueProvider.SetValue(target, value);
}
private static (bool isProxy, bool isInitialized) GetProxy(object proxy)
{
// this is pretty much what NHibernateUtil.IsInitialized() does.
switch (proxy)
{
case INHibernateProxy hibernateProxy:
return (true, !hibernateProxy.HibernateLazyInitializer.IsUninitialized);
case ILazyInitializedCollection initializedCollection:
return (true, initializedCollection.WasInitialized);
case IPersistentCollection persistentCollection:
return (true, persistentCollection.WasInitialized);
default:
return (false, false);
}
}
public object GetValue(object target)
{
object value = _valueProvider.GetValue(target);
(bool isProxy, bool isInitialized) = GetProxy(value);
if (isProxy)
{
if (isInitialized)
{
return value;
}
if (value is IEnumerable)
{
return Enumerable.Empty<object>();
}
return null;
}
return value;
}
}
public class NHibernateContractResolver : CamelCasePropertyNamesContractResolver {
protected override JsonContract CreateContract(Type objectType)
{
if (objectType.IsAssignableTo(typeof(IEntity)))
{
return base.CreateObjectContract(objectType);
}
return base.CreateContract(objectType);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
property.ValueProvider = new NHibernateProxyJsonValueProvider(property.ValueProvider);
return property;
}
}
Normal uninitialized lazy loaded properties will result in null in the json output.
Collection uninitialized lazy loaded properties will result in an [] empty array in json.
So for a lazy loaded property to appear in the json output you need to eagerly load it in the query or in code before serialization.
Usage:
JsonConvert.SerializeObject(entityToSerialize, new JsonSerializerSettings() {
ContractResolver = new NHibernateContractResolver()
});
Or globally in in ASP.NET Core Startup class
services.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new NHibernateContractResolver();
});
Using:
NET 5.0
NHibernate 5.3.8
JSON.NET latest via ASP.NET Core