structuremapstructuremap4

Register multiple instance based off of custom attribute with name list


I have a single rule that can handle multiple rule calls so I have created a custom attribute that is placed on the rule class. This attribute lists the names it is allowed to process. In structuremap I would like to register this same rule as multiple names by reading the custom attribute.

[RuleIdentifer(new string[] { "RunAction1","RunAction2","RunAction3" })]

I have tried to use the MissingNamedInstanceIs class but run into Bi-Directional dependency error. The following has been placed in the creation of the container after the Scan:

_.For<Rules.IRule>().MissingNamedInstanceIs.ConstructedBy("Pull Rule by Name from Attribute",r =>
{
    return r.GetAllInstances<Rules.IRule>().FirstOrDefault<Rules.IRule>(r1 =>
   {
                    var dnAttribute = r1.GetType().GetCustomAttributes(typeof(RuleIdentifer), true).FirstOrDefault() as RuleIdentifer;
                    if (dnAttribute != null && dnAttribute.Names.Contains<string>(r.RequestedName)) return true;
                    return true;
    });
 });

Is there a better way to do this in the scan section NameBy call:

x.AddAllTypesOf<Rules.IRule>().NameBy(t => t.Name);

Solution

  • When ahead and created my own RegistrationConvention. Work as expected now.

    public class RuleAttributeConvention : IRegistrationConvention
        {
            public void ScanTypes(TypeSet types, Registry registry)
            {
                // Only work on concrete types
                types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed).Where(typ => typeof(Rules.IRule).IsAssignableFrom(typ)).ToList().ForEach(t =>
                {
                    var dnAttribute = t.GetCustomAttributes(typeof(RuleIdentifer), true).FirstOrDefault() as RuleIdentifer;
                    if (null == dnAttribute) return;
                    foreach (var nm in dnAttribute.Names)
                    {                            
                      registry.For<Rules.IRule>().Use(t.Name).Name = nm;
                    }
                });
            }
        }