C# C使用字典和Func创建一个新实例,其中包含ctor args

C# C使用字典和Func创建一个新实例,其中包含ctor args,c#,dictionary,factory,func,C#,Dictionary,Factory,Func,我想知道是否有可能使用字典为给定某种解析器的类型创建一个新实例,其中新类型具有构造函数参数。本质上是一种工厂方法 我有一些有效的方法,尽管我希望有一种更干净的方法。我在Java中遇到了这个问题,并认为在C中这很容易——也许不是 因此,它基于给定的词典: class ResolverDictionary { static class Resolver<T> where T : ToResolve { public static Func<T, Re

我想知道是否有可能使用字典为给定某种解析器的类型创建一个新实例,其中新类型具有构造函数参数。本质上是一种工厂方法

我有一些有效的方法,尽管我希望有一种更干净的方法。我在Java中遇到了这个问题,并认为在C中这很容易——也许不是

因此,它基于给定的词典:

class ResolverDictionary
{
    static class Resolver<T> where T : ToResolve
    {
        public static Func<T, Resolved> Instance;
    }
    
    public ResolverDictionary Add<T>(Func<T, Resolved> resolver) where T : ToResolve
    {
        Resolver<T>.Instance = resolver;
        return this;
    }
    
    public Func<T, Resolved> Get<T>() where T : ToResolve
    {
        return Resolver<T>.Instance;
    }
}
字典

具有给定类型的解析函数。我想从ToResolve映射到resolve,将ToResolve字段传递到ToResolve构造函数参数。ToResolve和Resolve是场景的抽象类。解决问题,解决问题

因此,工作场景是:

Dictionary<Type, Func<ToResolve, Resolved>> map = new Dictionary<Type, Func<ToResolve, Resolved>>
{
    {
        typeof(ToResolve1), r =>
        {
            var tr = (ToResolve1) r;
            return new Resolved1(tr.x);
        }
    },
    {
        typeof(ToResolve2), r =>
        {
            var tr = (ToResolve2) r;
            return new Resolved2(tr.x);
        }
    }
};
简单的类声明如下:

public abstract class Resolved { }

public class Resolved1 : Resolved
{
    public readonly int x;

    public Resolved1(int x) => this.x = x;
}

public class Resolved2 : Resolved
{
    public readonly string x;

    public Resolved2(string x) => this.x = x;
}

public abstract class ToResolve { }

public class ToResolve1 : ToResolve
{
    public readonly int x;

    public ToResolve1(int x) => this.x = x;
}

public class ToResolve2 : ToResolve
{
    public readonly string x;

    public ToResolve2(string x) => this.x = x;
}
有没有更简洁的方法?理想情况下,无需将lambda包裹在几行上并使用显式转换


不使用AutoMapper。

看起来您只需要一堆重载方法,不确定这是您想要的简洁方式吗

public static class Resolver
{
    public static Resolved1 Resolve(ToResolve1 r) => new Resolved1(r.x);
    public static Resolved2 Resolve(ToResolve2 r) => new Resolved2(r.x);
}

var resolved1 = Resolver.Resolve(new ToResolve1(100));
var resolved2 = Resolver.Resolve(new ToResolve2("some string"));

看起来您只需要一堆重载方法,不确定这是您想要的简洁方式吗

public static class Resolver
{
    public static Resolved1 Resolve(ToResolve1 r) => new Resolved1(r.x);
    public static Resolved2 Resolve(ToResolve2 r) => new Resolved2(r.x);
}

var resolved1 = Resolver.Resolve(new ToResolve1(100));
var resolved2 = Resolver.Resolve(new ToResolve2("some string"));

字典不支持通用值,但是,您可以编写自己的自定义字典:

class ResolverDictionary
{
    static class Resolver<T> where T : ToResolve
    {
        public static Func<T, Resolved> Instance;
    }
    
    public ResolverDictionary Add<T>(Func<T, Resolved> resolver) where T : ToResolve
    {
        Resolver<T>.Instance = resolver;
        return this;
    }
    
    public Func<T, Resolved> Get<T>() where T : ToResolve
    {
        return Resolver<T>.Instance;
    }
}
可按如下方式使用:

var toResolve1 = new ToResolve1(100);
var resolved1 = map[toResolve1.GetType()];

var toResolve2 = new ToResolve2("some string");
var resolved2 = map[toResolve2.GetType()];
var dictionary = new ResolverDictionary()
    .Add((ToResolve1 r) => new Resolved1(r.x))
    .Add((ToResolve2 r) => new Resolved2(r.x));
    
var resolver1 = dictionary.Get<ToResolve1>();
var resolved1 = resolver1(new ToResolve1(100));

字典不支持通用值,但是,您可以编写自己的自定义字典:

class ResolverDictionary
{
    static class Resolver<T> where T : ToResolve
    {
        public static Func<T, Resolved> Instance;
    }
    
    public ResolverDictionary Add<T>(Func<T, Resolved> resolver) where T : ToResolve
    {
        Resolver<T>.Instance = resolver;
        return this;
    }
    
    public Func<T, Resolved> Get<T>() where T : ToResolve
    {
        return Resolver<T>.Instance;
    }
}
可按如下方式使用:

var toResolve1 = new ToResolve1(100);
var resolved1 = map[toResolve1.GetType()];

var toResolve2 = new ToResolve2("some string");
var resolved2 = map[toResolve2.GetType()];
var dictionary = new ResolverDictionary()
    .Add((ToResolve1 r) => new Resolved1(r.x))
    .Add((ToResolve2 r) => new Resolved2(r.x));
    
var resolver1 = dictionary.Get<ToResolve1>();
var resolved1 = resolver1(new ToResolve1(100));

我相信你可以通过保持字典的原样来做你想做的事情,但是在那里添加单独的方法来添加条目,如下所示:

static class Resolver {
    private static readonly Dictionary<Type, Func<ToResolve, Resolved>> _map = new Dictionary<Type, Func<ToResolve, Resolved>>();

    static Resolver() {
        Add((ToResolve1 tr) => new Resolved1(tr.x));
        Add((ToResolve2 tr) => new Resolved2(tr.x));
    }

    private static void Add<TToResolve, TResolved>(Func<TToResolve, TResolved> func) where TToResolve : ToResolve where TResolved : Resolved {
        _map[typeof(TToResolve)] = x => func((TToResolve) x);
    }

    // the only public interface, non-generic
    public static Resolved Resolve(ToResolve x) {
        return _map[x.GetType()](x);
    }
}

我相信你可以通过保持字典的原样来做你想做的事情,但是在那里添加单独的方法来添加条目,如下所示:

static class Resolver {
    private static readonly Dictionary<Type, Func<ToResolve, Resolved>> _map = new Dictionary<Type, Func<ToResolve, Resolved>>();

    static Resolver() {
        Add((ToResolve1 tr) => new Resolved1(tr.x));
        Add((ToResolve2 tr) => new Resolved2(tr.x));
    }

    private static void Add<TToResolve, TResolved>(Func<TToResolve, TResolved> func) where TToResolve : ToResolve where TResolved : Resolved {
        _map[typeof(TToResolve)] = x => func((TToResolve) x);
    }

    // the only public interface, non-generic
    public static Resolved Resolve(ToResolve x) {
        return _map[x.GetType()](x);
    }
}

您可以使用IoC框架来实现这一点:Ninject、DryIoc、StructureMap等。您基本上创建服务定位器,注册解析器,然后通过调用单个方法来解析它们。您希望这样做的原因是什么,而不是使用像上面提到的@eocron这样的IoC框架?这是为了你自己的启发,还是因为你不知道那些框架而试图编写一个穷人的DI?当通过配置文件读取类型时。相信我,我对国际奥委会很了解。它们在整个行业中被使用和滥用。他们肯定有自己的位置。在这里,我使用poormans DI来解决一个代码问题。您的示例代码似乎不完整,因为resolved1的类型是func,而toResolve1除了GetType1之外根本不使用。poor man DI方法有什么问题?表演写你自己的。它们有很多,我敢肯定它们被滥用了,就像你说的,但是我们可以告诉你整数也被滥用了。因为每个人都使用它们。你可以使用IoC框架:Ninject、DryIoc、StructureMap等。你基本上创建服务定位器,注册解析器,然后通过调用单个方法来解析它们。你想这样做的原因是什么,而不是使用像@eocron这样的IoC框架?这是为了你自己的启发,还是因为你不知道那些框架而试图编写一个穷人的DI?当通过配置文件读取类型时。相信我,我对国际奥委会很了解。它们在整个行业中被使用和滥用。他们肯定有自己的位置。在这里,我使用poormans DI来解决一个代码问题。您的示例代码似乎不完整,因为resolved1的类型是func,而toResolve1除了GetType1之外根本不使用。poor man DI方法有什么问题?表演写你自己的。它们有很多,我敢肯定它们被滥用了,就像你说的,但是我们可以告诉你整数也被滥用了。因为每个人都使用它们。回答很好,谢谢。它确实将类型与字典相关联,字典可以很好地用作抽象工厂。这完全回答了问题。回答得好,谢谢。它确实将类型与字典相关联,字典可以很好地用作抽象工厂。这完全回答了问题,回答得也不错。我在这和乔纳森的回答之间左右为难。这封装了类型。回答也不错。我在这和乔纳森的回答之间左右为难。这封装了类型。