我如何错误检查该工厂 Create使用带有参数的激活器的方法?

发布于 2025-01-04 12:46:11 字数 2135 浏览 1 评论 0原文

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

就好像我想要一个模板约束,表示“其中 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;
        }
    }
}

I'm not sure if/how I can check that the constructor actually exists before calling activator in this code (untested so might have bugs but hopefully the intention is clear).

Its as if I wanted a template constraint that says "where T has a constructor with signature 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;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无敌元气妹 2025-01-11 12:46:11

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

无论如何:

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);
}

Have you considered using interfaces instead of factories? You can get much better results, and you don't run into problems like this.

Anyway:

where T : new()

Only works for parameterless constructors. When you have that constraint, you can do the following, without reflection:

T obj = new T();

You're going to have to check manually.

ConstructorInfo ctor = typeof(T).GetConstructor(new Type[] { EntityConnection });
if (ctor == null)
{
    // Handle an unwanted type.
}
else
{
    return (T)ctor.Invoke(entityConnection);
}
归途 2025-01-11 12:46:11

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

一种选择是需要工厂委托:

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

然后您可以使用:

Create(connection => new Whatever(connection))

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

No, you can't - the only constructor-related generic constraint available is new() which requires a parameterless constructor.

One option is to require a factory delegate instead:

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

Then you can use:

Create(connection => new Whatever(connection))

or anything else that will build the appropriate object. It's more flexible, safer, and performs better too. (The latter is probably irrelevant, admittedly...)

鸠魁 2025-01-11 12:46:11

Type.GetConstructor 方法 (Type())

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

Type.GetConstructor Method (Type())

Searches for a public instance constructor whose parameters match the
types in the specified array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文