I'm new to Unity and I'm having a hard time trying to figure out how to expand Unity's concept of Auto Factory. Unity provides out of box the ability to create factories using Func in the place of the parameter itself. Like that:
public class Foo
{
private readonly Func<IBar> _barFactory;
public Foo(Func<IBar> barFactory)
{
_bar = barFactory;
}
}
The thing is, there are places where the class created by the factory needs some parameters and I'll only know those parameters in run time. Other than that, the number and type of those parameters varies from class to class.
What I'm looking for is something similar to Autofac DelegateFacotry, but I would like to keep the Unity's feeling. So, I want to make Unity to work like that:
public class Foo
{
private readonly Func<int, string, IBar> _barFactory;
public Foo(Func<int, string, IBar> barFactory)
{
_bar = barFactory;
}
}
The above code does not work, because Unity does work with that constructor, but it is exactly what I'm looking for.
I have tried use BuilderStrategy but it boils down to either Expression or IL generation. Before going down that path I would like to check for other options.
Is any one experienced enough with Unity who can help me with that?
Here are the constrains I have:
Keep Unity's concept of using Func
Do not need to register every single Func within the container
The constructor should accept Func from Func to Func (Func is handled already)
Changing the container is not an option
I hope I was clear enough. If I was not, please let me know.
Edit 1: I understand I can use abstract factories directly. But, the first goal is to keep Unity's feeling.
I don't like to answer my own questions, but I was able to somehow solve the problem and I believe the solution is good enough that others may be interested. I looked at Unity's source code and got the basic idea from there. I also read a couple of posts regarding Unity. Here it is:
First, I had to create a class that inherited from IBuildPlanPolicy. It is long because I left some supporting classes within the class itself:
public class AutomaticFactoryBuilderPolicy : IBuildPlanPolicy
{
private readonly Dictionary<Type, Type> _callables =
new Dictionary<Type, Type>
{
{typeof(Func<,>), typeof(CallableType<,>)},
{typeof(Func<,,>), typeof(CallableType<,,>)},
{typeof(Func<,,,>), typeof(CallableType<,,,>)},
{typeof(Func<,,,,>), typeof(CallableType<,,,,>)}
};
public void BuildUp(IBuilderContext context)
{
if (context.Existing == null)
{
var currentContainer = context.NewBuildUp<IUnityContainer>();
var buildKey = context.BuildKey;
string nameToBuild = buildKey.Name;
context.Existing = CreateResolver(currentContainer, buildKey.Type, nameToBuild);
}
}
private Delegate CreateResolver(IUnityContainer currentContainer,
Type typeToBuild, string nameToBuild)
{
Type[] delegateTypes = typeToBuild.GetGenericArguments();
Type func = typeToBuild.GetGenericTypeDefinition();
Type callable = _callables[func];
Type callableType = callable.MakeGenericType(delegateTypes);
Type delegateType = func.MakeGenericType(delegateTypes);
MethodInfo resolveMethod = callableType.GetMethod("Resolve");
object callableObject = Activator.CreateInstance(callableType, currentContainer, nameToBuild);
return Delegate.CreateDelegate(delegateType, callableObject, resolveMethod);
}
private class CallableType<T1, TResult>
{
private readonly IUnityContainer _container;
private readonly string _name;
public CallableType(IUnityContainer container, string name)
{
_container = container;
_name = name;
}
public TResult Resolve(T1 p1)
{
return _container.Resolve<TResult>(_name, new OrderedParametersOverride(new object[] { p1 }));
}
}
private class CallableType<T1, T2, TResult>
{
private readonly IUnityContainer _container;
private readonly string _name;
public CallableType(IUnityContainer container, string name)
{
_container = container;
_name = name;
}
public TResult Resolve(T1 p1, T2 p2)
{
return _container.Resolve<TResult>(_name, new OrderedParametersOverride(new object[] { p1, p2 }));
}
}
private class CallableType<T1, T2, T3, TResult>
{
private readonly IUnityContainer _container;
private readonly string _name;
public CallableType(IUnityContainer container, string name)
{
_container = container;
_name = name;
}
public TResult Resolve(T1 p1, T2 p2, T3 p3)
{
return _container.Resolve<TResult>(_name, new OrderedParametersOverride(new object[] { p1, p2, p3 }));
}
}
private class CallableType<T1, T2, T3, T4, TResult>
{
private readonly IUnityContainer _container;
private readonly string _name;
public CallableType(IUnityContainer container, string name)
{
_container = container;
_name = name;
}
public TResult Resolve(T1 p1, T2 p2, T3 p3, T4 p4)
{
return _container.Resolve<TResult>(_name, new OrderedParametersResolverOverride(new object[] { p1, p2, p3, p4 }));
}
}
}
It is pretty straightforward. The trick is to create one CallableType for each Func I want to handle. It is not as dynamic as I first wanted, but in order to make it more dynamic I believe I would have to deal with either IL or Expression Trees. The way I have it now is good enough for me.
Second, Unity handles parameters by name but I had to deal with them by order. That's where OrderedParametersResolverOverride comes into play (this class is used in the code above. Check CallableType classes):
public class OrderedParametersResolverOverride : ResolverOverride
{
private readonly Queue<InjectionParameterValue> _parameterValues;
public OrderedParametersResolverOverride(IEnumerable<object> parameterValues)
{
_parameterValues = new Queue<InjectionParameterValue>();
foreach (var parameterValue in parameterValues)
{
_parameterValues.Enqueue(InjectionParameterValue.ToParameter(parameterValue));
}
}
public override IDependencyResolverPolicy GetResolver(IBuilderContext context, Type dependencyType)
{
if (_parameterValues.Count < 1)
return null;
var value = _parameterValues.Dequeue();
return value.GetResolverPolicy(dependencyType);
}
}
Those two classes deal with Func creation. The next step is to add that builder to Unity's pipeline. We'll need to create a UnityContainerExtension:
public class AutomaticFactoryExtension: UnityContainerExtension
{
protected override void Initialize()
{
var automaticFactoryBuilderPolicy = new AutomaticFactoryBuilderPolicy();
Context.Policies.Set(typeof(Microsoft.Practices.ObjectBuilder2.IBuildPlanPolicy),
automaticFactoryBuilderPolicy,
new Microsoft.Practices.ObjectBuilder2.NamedTypeBuildKey(typeof(Func<,>)));
Context.Policies.Set(typeof(Microsoft.Practices.ObjectBuilder2.IBuildPlanPolicy),
automaticFactoryBuilderPolicy,
new Microsoft.Practices.ObjectBuilder2.NamedTypeBuildKey(typeof(Func<,,>)));
Context.Policies.Set(typeof(Microsoft.Practices.ObjectBuilder2.IBuildPlanPolicy),
automaticFactoryBuilderPolicy,
new Microsoft.Practices.ObjectBuilder2.NamedTypeBuildKey(typeof(Func<,,,>)));
Context.Policies.Set(typeof(Microsoft.Practices.ObjectBuilder2.IBuildPlanPolicy),
automaticFactoryBuilderPolicy,
new Microsoft.Practices.ObjectBuilder2.NamedTypeBuildKey(typeof(Func<,,,,>)));
}
}
The last piece is to actually add that class to Unity's pipeline:
IUnityContainer container = new UnityContainer();
container.AddExtension(new AutomaticFactoryExtension());
The rest of the registration is standard.
Now it is possible to have constructors from Func<> to Fun<,,,,>. The following constructor, for instance, is now handled (assuming it is possible to resolve IFoo):
public class Bar
{
private readonly Func<int, string, IFoo> _fooFactory;
public Bar(Func<int, string, IFoo> fooFactory)
{
_fooFactory = fooFactory;
}
}
Let me know if there are any question.
Hope this helps.
Have you thought about creating a delegate and registering and instance of that with Unity? That way you'd have named parameters and comments on those parameters, as well as the delegate itself. Then you wouldn't need to create build policies, and your code would be more readable.
I have a strange problem with unity BuildUp method. I have one interface that's mapped to three classes. I have given a name to each mapping.
Now I need to inject the dependency in an existing object (it's an attribute so I don't have control over lifetime). I call the BuildUp method to inject the dependency, but it always throws an exception which says that the interface is not mapped.
If I map the interface to one type only and I remove the mappingname, the BuildUp method works.
If I map the interface to one type only and I specify the mappingname, the BuildUp method fail.
I have tried registering types in configuration and code and nothing changes.
I suspect this is a bug, but I would like to know if anyone else has another idea.
This is how i call buildup method:
var newAttr = _container.BuildUp(myAttribute.GetType(), myAttribute, "Mapping1");
I tried to follow your scenario and this sample works
var container = new UnityContainer();
container.RegisterType<IFoo, One>("1", new InjectionProperty("Bar", "1"));
container.RegisterType<IFoo, Two>("2", new InjectionProperty("Bar", "2"));
container.RegisterType<IFoo, Three>("3", new InjectionProperty("Bar", "3"));
One one = new One();
container.BuildUp(one.GetType(), one, "1");
Assert.AreEqual("1", one.Bar);
public interface IFoo
{
string Bar { get; set; }
}
public class One : IFoo
{
public string Bar { get; set; }
}
public class Two : IFoo
{
public string Bar { get; set; }
}
public class Three : IFoo
{
public string Bar { get; set; }
}
Update
var container = new UnityContainer();
container.RegisterType<Person>(new InjectionProperty("Foo"));
container.RegisterType<IFoo, One>("1");
container.RegisterType<IFoo, Two>("2");
container.RegisterType<IFoo, Three>("3");
Person person = container.Resolve<Person>("1");
Assert.IsNotNull(person.Foo);
Assert.IsInstanceOfType(person.Foo, typeof(One));
public class Person
{
public IFoo Foo { get; set; }
}
I guess this is what you mean? Short answer: That's not the way Unity works.
Long answer: You will have to specify a ResolverOverride that does that for you. But even that is not enough as you want the container to create the value you want to inject for you. So you would need to specify a ResolvedParameter as the value for your ResolverOverride. With Unity's out-of-the-box parts the Resolve would look like this
Person person = container.Resolve<Person>(new PropertyOverride("Foo", new ResolvedParameter(typeof(IFoo), "1")));
Or you can use this custom override instead
public class NamedPropertyOverride : ResolverOverride
{
private readonly string propertyName;
private readonly string registrationName;
public NamedPropertyOverride(string propertyName, string registrationName)
{
this.propertyName = propertyName;
this.registrationName = registrationName;
}
public override IDependencyResolverPolicy GetResolver(IBuilderContext context, Type dependencyType)
{
var currentOperation = context.CurrentOperation as ResolvingPropertyValueOperation;
if (currentOperation != null &&
currentOperation.PropertyName == this.propertyName)
{
Type propertyType = currentOperation
.TypeBeingConstructed
.GetProperty(currentOperation.PropertyName, BindingFlags.Instance | BindingFlags.Public)
.PropertyType;
return new NamedTypeDependencyResolverPolicy(propertyType, this.registrationName);
}
return null;
}
}
Change the line that contains the call to Resolve in the above sample to this one
Person person = container.Resolve<Person>(new NamedPropertyOverride("Foo", "1"));
That should do the trick.
Consider the following snippet;
public enum ReportType {Monthly,Quarterly}
public class BaseReport
{
public ReportType ReportType {get;set;}
}
public class MonthlyReport : BaseReport
{
public String month = "January"
public MonthlyReport() { ReportType = Monthly;}
}
public class Foo
{
public virtual void AddReport(BaseReport report);
}
[Test]
public void Test1()
{
var mock = new Mock<Foo>(){CallBase =true};
var report = new MonthlyReport();
mock.Object.AddReport(report);
}
Well I am trying to verify if the AddReport() is called with certain parameter here;
mock.Verify(x => x.AddReport(It.Is<MonthlyReport>(p => p.month == "January" &&
p.ReportType == ReportType.Monthly)));
As I feared, it doesn't work with a MonthlyReport parameter for Is<> even though it is derived from BaseReport. If I use Is,then I can't use p.month in the expression, and I am not that proficient with c# to know whether I can use if(p is MonthlyReport) in a lambda expression or more importantly, it would work as intended.
How can I approach this problem? Please note that the mock is partial, Although I can live with
Setup approach with callbacks if it is neatly solves my problem.
Any pointers would be greatly appreciated...
I have a class like this. Property "isPag" is based on filed "ecboardid", I found that when ecboardid is changed, UI controls seem not be able to detect that "isPag" is also changed. So, how to make a property like this bindable?
[Bindable]
public class Encoder extends EventDispatcher
{
public var ecboardid : String;
/*-.........................................Methods..........................................*/
public function copyFrom(newEncoder:Encoder):void
{
ecboardid = newEncoder.ecboardid;
this.dispatchEvent(new Event('isPagChanged'));
}
[Bindable (event="isPagChanged")]
public function get isPag():Boolean
{
if(this.ecboardid != null)
{
if(this.ecboardid.search('xxx') != -1)
{
return false;
}
return true;
}
else
{
return false;
}
}
}
Edit:
If I change the property to a static function,
[Bindable]
public class Encoder extends EventDispatcher
{
public var ecboardid : String;
/*-.........................................Methods..........................................*/
public function copyFrom(newEncoder:Encoder):void
{
ecboardid = newEncoder.ecboardid;
this.dispatchEvent(new Event('isPagChanged'));
}
public static function isPag(String ecboardid ):Boolean
{
if(ecboardid != null)
{
if(ecboardid.search('xxx') != -1)
{
return false;
}
return true;
}
else
{
return false;
}
}
}
Will bind like this :
visible = {Encoder.isPag(encoder.ecboardid)}
work? Will visible change when encoder.ecboardid change?
I don't believe you can make read only properties Bindable, since Flex uses calls to the setter method for a property to issue the change events. Take a look here at the section on binding to properties of objects.
You need to have a setter as well as a getter.
Also, you have the class marked as bindable, if you weren't specifying the event name, then the [Bindable] on the method would be redundant.
Usually the compiler complains if you have just a getter and no setter and try to mark it [Bindable]
Code like this:
visible = {Encoder.isPag(encoder.ecboardid)}
Isn't how binding works. The {var} notation is for use in MXML. And isPag isn't static, so you can't refer to it as a class property. You need an instance of the Encoder class for this to be legal.
This is a simple change - just create getters/setters and dispatch your change event in the setter (after changing the value), like this:
private var _ecboardid : String;
public function get ecboardid():String
{
return _ecboardid;
}
public function set ecboardid(value:String):void
{
_ecboardid = value;
this.dispatchEvent(new Event('isPagChanged'));
}
My Grails application has a large number of enums that look like this:
public enum Rating {
BEST("be"), GOOD("go"), AVERAGE("av"), BAD("ba"), WORST("wo")
final String id
private RateType(String id) {
this.id = id
}
static public RateType getEnumFromId(String value) {
values().find {it.id == value }
}
}
If I have a command object such as this:
class MyCommand {
Rating rating
}
I would like to (for example) automatically convert a request parameter with value "wo" to Rating.WORST.
The procedure for defining custom converters is described here (in the context of converting Strings to Dates). Although this procedure works fine, I don't want to have to create a class implementing PropertyEditorSupport for each of my enums. Is there a better alternative?
I found a solution I'm pretty happy with.
Step 1: Create an implementation of PropertyEditorSupport to convert text to/from the relevant Enum
public class EnumEditor extends PropertyEditorSupport {
private Class<? extends Enum<?>> clazz
public EnumEditor(Class<? extends Enum<?>> clazz) {
this.clazz = clazz
}
public String getAsText() {
return value?.id
}
public void setAsText(String text) {
value = clazz.getEnumFromId(text)
}
}
Step 2: Define a class that registers EnumEditor as a converter for the various enum classes. To change the list of enum classes that are bindable by id, just modify BINDABLE_ENUMS
public class CustomPropertyEditorRegistrar implements PropertyEditorRegistrar {
private static final String REQUIRED_METHOD_NAME = 'getEnumFromId'
// Add any enums that you want to bind to by ID into this list
private static final BINDABLE_ENUMS = [Rating, SomeOtherEnum, SomeOtherEnum2]
public void registerCustomEditors(PropertyEditorRegistry registry) {
BINDABLE_ENUMS.each {enumClass ->
registerEnum(registry, enumClass)
}
}
/**
* Register an enum to be bound by ID from a request parameter
* #param registry Registry of types eligible for data binding
* #param enumClass Class of the enum
*/
private registerEnum(PropertyEditorRegistry registry, Class<? extends Enum<?>> enumClass) {
boolean hasRequiredMethod = enumClass.metaClass.methods.any {MetaMethod method ->
method.isStatic() && method.name == REQUIRED_METHOD_NAME && method.parameterTypes.size() == 1
}
if (!hasRequiredMethod) {
throw new MissingMethodException(REQUIRED_METHOD_NAME, enumClass, [String].toArray())
}
registry.registerCustomEditor(enumClass, new EnumEditor(enumClass))
}
}
Step 3: Make Spring aware of the registry above by defining the following Spring bean in grails-app/conf/spring/resources.grooovy
customPropertyEditorRegistrar(CustomPropertyEditorRegistrar)
So the default Databinding binds on the Enum name and not a separately defined property of the Enum. You can either create your own PropertyEditor as you have mentioned or do a work-around similar to this:
class MyCommand {
String ratingId
Rating getRating() {
return Rating.getEnumFromId(this.ratingId)
}
static constraints = {
ratingId(validator:{val, obj -> Rating.getEnumFromId(val) != null })
}
}