如何错误检查此工厂创建<T>使用带参数的激活器的方法?



我不确定在调用该代码中的activator之前,是否/如何检查构造函数是否确实存在(未经测试,因此可能存在错误,但希望其意图是明确的)。

就好像我想要一个模板约束,上面写着"其中T有一个带有签名S的构造函数"。

public class EntityContainerFactory
{
    public EntityContainerFactory(string sqlServerName, string databaseName, string metaData)
        : this(sqlServerName, databaseName, metaData, "System.Data.EntityClient")
    {
    }
    public EntityContainerFactory(string sqlServerName, string databaseName, string metaData, string dataProviderName)
    {
        SqlServerName = sqlServerName;
        DatabaseName = databaseName;
        Metadata = metaData;
        DataProviderName = dataProviderName;
    }
    // --> IS THERE ANY WAY TO CHECK THAT T HAS 
    //     A CONSTRUCTOR THAT TAKES AN ENTITY CONNECTION?
    public T Create<T>()
    {
        return (T)Activator.CreateInstance(typeof(T), CreateEntityConnection());
    }
    EntityConnection CreateEntityConnection()
    {
        SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
        sqlBuilder.DataSource = SqlServerName;
        sqlBuilder.InitialCatalog = DatabaseName;
        sqlBuilder.IntegratedSecurity = true;
        EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
        entityBuilder.Provider = DataProviderName;
        entityBuilder.ProviderConnectionString = sqlBuilder.ToString();
        entityBuilder.Metadata = Metadata;
        return new EntityConnection(entityBuilder.ConnectionString);
    }
    public string DatabaseName { get; set; }
    public string SqlServerName { get; set; }
    public string DataProviderName { get; set; }
    private string metaData;
    public string Metadata
    {
        get
        {
            string result;
            if (!this.metaData.StartsWith("res://"))
            {
                result = string.Format(@"res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl", this.metaData);
            }
            else
            {
                result = this.metaData;
            }
            return result;
        }
        set
        {
            this.metaData = value;
        }
    }
}

您是否考虑过使用接口而不是工厂?你可以得到更好的结果,而且你不会遇到这样的问题。

总之:

where T : new()

仅适用于无参数构造函数。当你有这种限制时,你可以做以下事情,而不需要反思:

T obj = new T();

您将不得不手动检查。

ConstructorInfo ctor = typeof(T).GetConstructor(new Type[] { EntityConnection });
if (ctor == null)
{
    // Handle an unwanted type.
}
else
{
    return (T)ctor.Invoke(entityConnection);
}

不,不能-唯一可用的与构造函数相关的通用约束是new(),它需要一个无参数构造函数。

一种选择是需要一名工厂代表:

public T Create<T>(Func<EntityConnection, T> factory)
{
    return factory(CreateEntityConnection());
}

然后你可以使用:

Create(connection => new Whatever(connection))

或任何其他将构建适当对象的东西。它更灵活、更安全,性能也更好。(无可否认,后者可能无关紧要…)

Type.GetConstructor方法(Type())

搜索参数与指定数组中的类型。

相关内容

  • 没有找到相关文章

最新更新