Skip to content

Instantly share code, notes, and snippets.

@jagregory
Created September 23, 2010 15:22
Show Gist options
  • Save jagregory/593792 to your computer and use it in GitHub Desktop.
Save jagregory/593792 to your computer and use it in GitHub Desktop.
public class SomeService
{
public string GetValues()
{
return "huzzah";
}
}
public class Person
{
public virtual long Id { get; set; }
public virtual DateTime CobDate { get; set; }
readonly SomeService someService = Mixin.Mark<SomeService>();
public virtual string GetSomeValues()
{
return someService.GetValues();
}
}
public class Mixin
{
/// <summary>
/// Mark a field as a mixin target
/// </summary>
public static T Mark<T>()
{
var proxyFactory = new ProxyFactory();
return proxyFactory.CreateProxy<T>(new MixinWrapper(), typeof(IMixin));
}
/// <summary>
/// Hydrate any mixin fields with an actual instance. Mixin fields are determined by:
/// * Being of a type that implements IMixin
/// * Having a value of Mixin.Mark();
/// </summary>
public static void Hydrate<T>(T instance)
{
var mixinTargets = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Select(x => new { field = x, mixinType = x.FieldType, currentValue = x.GetValue(instance) })
.Where(x => typeof(IMixin).IsAssignableFrom(x.currentValue.GetType()) || typeof(IMixin).IsAssignableFrom(x.field.FieldType));
foreach (var target in mixinTargets)
{
var mixinInstance = Activator.CreateInstance(target.mixinType); // YOUR CONTAINER HERE!
target.field.SetValue(instance, mixinInstance);
}
}
private class MixinWrapper : IInvokeWrapper
{
public void BeforeInvoke(InvocationInfo info)
{ }
public object DoInvoke(InvocationInfo info)
{
throw new UninjectedMixinException();
}
public void AfterInvoke(InvocationInfo info, object returnValue)
{ }
}
}
public class UninjectedMixinException : Exception
{
}
public interface IMixin
{}
@jagregory
Copy link
Author

Random idea for mixins. Not sure this is any better than constructor injection, but it certainly is clever ;)

@jagregory
Copy link
Author

Usage:

In your entity:

MyService someService = Mixin.Mark<MyService>();

or
MyService someServiceThatImplementsIMixin;

After fetching/creating your entity (probably do-able using an NH interceptor):

Mixin.Hydrate(my_entity);

Ta-da, your mixin fields have values!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment