Constructor Argument Enums and Magic Strings

隐身守侯 提交于 2019-12-23 17:27:48

问题


I am working on my c# .net application and use implement IoC/DI pattern using Ninject, Now Ninject has a class named ConstructorArgument which takes two arguments(argName,argValue).

So i need to pass static argName something like this

new ConstructorArgument("strVar","")

passing hardcoded string does not seems like a good option.

So i want to create something like dynamics enums using reflection for the constructor arguments, so i dont need to pass hardcoded strings.

Please guide me through this process or suggest me something else to achieve this.


回答1:


like dynamics enums

There is no such construct readily available. If you really hate the strings, you could write some kind of expression-tree lambda (i.e. () => new Foo(strVal: "") or () => new Foo(""), however - that a: is a lot of work, and b: won't work well if there are other parameters being provided by the container.

To be honest, this is a bit of a non-issue, especially since named arguments mean that parameter names should be treated as a contract. IMO, just use the string. If it worries you, make sure you cover the scenario in a unit test, so that you find out early if it changes.




回答2:


I agree with @Mark Gravell's stance, except that obfuscators can rename parameters for non-public ctors so the advice doesn't apply in that specific case, so in some cases, you need to whack on a [Obfuscation] on the parameter to preserve the name in some instances.

But I have built nonsense like this which would answer your question. Please don't use it as I regret writing it!

static class StaticReflection<TClass>
{
    static string PublicConstructorParameterName<TParameter>()
    {
        return typeof( TClass ).GetConstructors( BindingFlags.Public | BindingFlags.Instance ).Single().GetParameters().Where( param => param.ParameterType == typeof( TParameter ) ).Single().Name;
    }

    internal static ConstructorArgument CreateConstructorArgument<TParameter>( TParameter value )
    {
        return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), value );
    }

    internal static ConstructorArgument CreateConstructorArgument<TParameter>( Func<IContext, TParameter> argumentResolver )
    {
        return new ConstructorArgument( PublicConstructorParameterName<TParameter>(), context => (object)argumentResolver( context ) );
    }
}

Which works like this:

public class StaticReflectionFacts
{
    public class X2
    {
    }

    public class X
    {
        public X( object param1, X2 param2 )
        {
        }
    }

    [Fact]
    static void DeriveNinjectConstructorArgumentFromPublic()
    {
        var newArg = StaticReflection<X>.CreateConstructorArgument( new X2() );
        Assert.Equal( "param2", newArg.Name );
    }
}



回答3:


I have imlemented this:

    public string GiveConstuctorArgumentName(Type class, Type constructorArgument)
    {
       var cons = class.GetConstructors();

       foreach (var constructorInfo in cons)
       {
          foreach (var consParameter in constructorInfo.GetParameters())
          {
             if (consParameter.ParameterType == constructorArgument)
             {
                return consParameter.Name;
             }
          }
       }

       throw new InstanceNotFoundException();
    }

Its without LINQ, but its a good start point to understand how its work.



来源:https://stackoverflow.com/questions/6607171/constructor-argument-enums-and-magic-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!