3

Lazy<>小さな依存性注入フレームワークがあり、インスタンスを動的に解決しようとしています。アイデアは、そのようなことをすることです:

DIContainer.Register<IDbCommand,SqlCommand>();

var lazyCommand = DIContainer.Resolve<Lazy<IDbCommand>>();

先日、Autofac がそれを可能にしたという記事を読みました。

Lazy<>そのインスタンスのコンストラクターを設定しようとして立ち往生しています。次のテスト コードでは、目的の型コンストラクターが を予期しているため、例外がスローされますFunc<arg>が、私は を渡していFunc<Object>ます。

    static readonly Type _lazyType = typeof(Lazy<>);
    static Object ResolveTest(Type type)
    {
        if (type.IsGenericType && type.GetGenericTypeDefinition() == _lazyType)
        {
            var arg = type.GetGenericArguments()[0];

            return Activator.CreateInstance(_lazyType.MakeGenericType(arg), new Func<Object>(() => ResolveType(arg)));
        }
        else 
            return ResolveType(type);
    }

Lazy<>コンストラクター パラメーターに適したデリゲートを作成する方法について、私はアイデアがありません。何か案が?

乾杯。

4

3 に答える 3

2

このアプリは「True」と「0」を出力します。つまり、あなたが望むように構築されResolveTest(typeof(Lazy<int>))たオブジェクトを返します。Lazy<int>

using System;
using System.Linq.Expressions;

namespace TestApp
{
    public class Class1
    {
        public static void Main()
        {
            object lazyInt = ResolveTest(typeof(Lazy<int>));
            Console.WriteLine(lazyInt.GetType() == typeof(Lazy<int>));
            Console.WriteLine(((Lazy<int>)lazyInt).Value);
        }

        static readonly Type _lazyType = typeof(Lazy<>);
        static Object ResolveTest(Type type)
        {
            if (type.IsGenericType && type.GetGenericTypeDefinition() == _lazyType)
            {
                var arg = type.GetGenericArguments()[0];
                var lazyArgType = _lazyType.MakeGenericType(arg);
                var funcArgType = typeof(Func<>).MakeGenericType(arg);
                var funcCtor = lazyArgType.GetConstructor(new[] { funcArgType });
                Expression<Func<object>> f = () => ResolveTest(arg);
                var func = typeof(Class1).GetMethod("BuildCastedThing").MakeGenericMethod(arg).Invoke(null, new[] { f });
                var arguments = new object[] { func };

                var retVal = funcCtor.Invoke(arguments);
                return retVal;
            }
            else
                return ResolveType(type);
        }
        public static object ResolveType(Type type)
        {
            return Activator.CreateInstance(type);
        }
        public static Func<T> BuildCastedThing<T>(Expression<Func<object>> f)
        {
            Expression<Func<T>> expr =
                Expression.Lambda<Func<T>>(
                    Expression.Convert(
                        Expression.Invoke(f),
                        typeof(T)));

            return expr.Compile();
        }
    }
}

ResolveTestこれはジェネリックとして書き直す方法ですResolve<T>(例: Resolve<int>returns Lazy<int>)。ResolveTest(typeof(int))を返す に相当するものがないため、これは少し異なりますint

static Lazy<T> Resolve<T>()
{
    var arg = typeof(T);
    return new Lazy<T>(() => (T)ResolveType(arg));
}

またはジェネリックでResolveType<T>

static Lazy<T> Resolve<T>()
{
    return new Lazy<T>(() => ResolveType<T>());
}
public static T ResolveType<T>()
{
    return Activator.CreateInstance<T>();
}
于 2013-10-23T15:42:29.630 に答える