Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 键入调用Activator.CreateInstance()实例的方法的安全方式?_C# - Fatal编程技术网

C# 键入调用Activator.CreateInstance()实例的方法的安全方式?

C# 键入调用Activator.CreateInstance()实例的方法的安全方式?,c#,C#,在下面的代码中,hs.Add(…)无法编译。声明hs为dynamic应该可以工作,但我尽量不使用它。有没有一种类型安全的方法 void F(string colName, DbDataReader reader1, DbDataReader reader2) { // .... loop reader1.Read(); reader2.Read() var x = reader1[colName]; var type = x.GetType(); var hs =

在下面的代码中,
hs.Add(…)
无法编译。声明
hs
dynamic
应该可以工作,但我尽量不使用它。有没有一种类型安全的方法

void F(string colName, DbDataReader reader1, DbDataReader reader2)
{
    // .... loop reader1.Read(); reader2.Read()
    var x = reader1[colName];
    var type = x.GetType();
    var hs = Activator.CreateInstance(typeof(HashSet<>).MakeGenericType(type)); 
      // change var to dynamic will work. Trying not to use it.
    hs.Add(x); // Error
    // ...
    hs.Contains(reader2[colName]); // Error
但它有一个错误

System.InvalidCastException: Unable to cast object of type
  'System.Collections.Generic.HashSet`1[System.Int32]' to type
  'System.Collections.Generic.HashSet`1[System.Object]'.

正如Peter指出的,
Activator
是一种使用反射动态创建对象的方法,而不需要在构建时知道对象的类型。此方法中的类型“安全”是通过检查类型或处理类型转换错误,如使用
Convert.ChangeType

请注意,DbDataReader有一些帮助函数用于处理诸如GetFieldType和GetString之类的类型,这些类型可以使用列索引来调用。例如:

int myColumn = 0;
var type = reader1.GetFieldType(myColumn);
if (type == typeof(string))
   string myValue = reader1.GetString(myColumn);

它或多或少归结为一些使用分支语句而不是反射来管理类型的方法。另外,您应该注意到,许多ORM(如EntityFramework或Dapper)都为您处理了大量此类类型转换。

正如Peter指出的,
Activator
是一种使用反射来动态创建对象的方法,而在构建时不知道对象的类型。此方法中的类型“安全”是通过检查类型或处理类型转换错误,如使用
Convert.ChangeType

请注意,DbDataReader有一些帮助函数用于处理诸如GetFieldType和GetString之类的类型,这些类型可以使用列索引来调用。例如:

int myColumn = 0;
var type = reader1.GetFieldType(myColumn);
if (type == typeof(string))
   string myValue = reader1.GetString(myColumn);

它或多或少归结为一些使用分支语句而不是反射来管理类型的方法。另外,您应该注意到,许多ORM(如EntityFramework或Dapper)为您处理了大量此类类型转换。

您似乎希望对标量值执行某种设置操作(交集?排除?)。您可以使用泛型(和
DbDataReader.GetFieldValue
)解决此问题,而无需使用反射或
Activator
,如下所示:

如果要从静态(即编译时)已知
colName
列类型的调用站点调用此
F
函数,请将
F
转换为通用方法:

void F<T>( String colName, DbDataReader reader1, DbDataReader reader2 )
{
    Itn32 rdr1Idx = reader1.GetOrdinal( colName );
    Itn32 rdr2Idx = reader2.GetOrdinal( colName );

    HashSet<T> hashSet = new HashSet<T>();

    while( reader1.Read() && reader2.Read() )
    {
        T value1 = reader1.GetFieldValue<T>( rdr1Idx );
        T value2 = reader2.GetFieldValue<T>( rdr2Idx );

        hashSet.Add( value1 );
        hashSet.Add( value2 );
        // etc - whatever logic you want here.
    }
}

似乎您想要对标量值执行某种集合操作(交集?排除?)。您可以使用泛型(和
DbDataReader.GetFieldValue
)解决此问题,而无需使用反射或
Activator
,如下所示:

如果要从静态(即编译时)已知
colName
列类型的调用站点调用此
F
函数,请将
F
转换为通用方法:

void F<T>( String colName, DbDataReader reader1, DbDataReader reader2 )
{
    Itn32 rdr1Idx = reader1.GetOrdinal( colName );
    Itn32 rdr2Idx = reader2.GetOrdinal( colName );

    HashSet<T> hashSet = new HashSet<T>();

    while( reader1.Read() && reader2.Read() )
    {
        T value1 = reader1.GetFieldValue<T>( rdr1Idx );
        T value2 = reader2.GetFieldValue<T>( rdr2Idx );

        hashSet.Add( value1 );
        hashSet.Add( value2 );
        // etc - whatever logic you want here.
    }
}

下面是使用反射的版本

var x = 1;

var type = x.GetType();
var hs = Activator.CreateInstance(typeof(HashSet<>).MakeGenericType(type));
// hs.Add(x); // Error
var method = hs.GetType().GetMethod("Add");

method.Invoke(hs, new object[] { x });
method.Invoke(hs, new object[] { x + 1 });
var x=1;
var type=x.GetType();
var hs=Activator.CreateInstance(typeof(HashSet).MakeGenericType(type));
//加上(x);//错误
var method=hs.GetType().GetMethod(“添加”);
调用(hs,新对象[]{x});
调用(hs,新对象[]{x+1});

如果
.Invoke()
需要被调用数百万次,那么它比
dynamic
要慢<代码>动态似乎需要更多的时间进行设置。

这是使用反射的版本

var x = 1;

var type = x.GetType();
var hs = Activator.CreateInstance(typeof(HashSet<>).MakeGenericType(type));
// hs.Add(x); // Error
var method = hs.GetType().GetMethod("Add");

method.Invoke(hs, new object[] { x });
method.Invoke(hs, new object[] { x + 1 });
var x=1;
var type=x.GetType();
var hs=Activator.CreateInstance(typeof(HashSet).MakeGenericType(type));
//加上(x);//错误
var method=hs.GetType().GetMethod(“添加”);
调用(hs,新对象[]{x});
调用(hs,新对象[]{x+1});

如果
.Invoke()
需要被调用数百万次,那么它比
dynamic
要慢<代码>动态似乎需要更多的时间来设置。

什么是
参数
?为什么
动态
工作?你的问题很具体。到目前为止你试过什么?您是否要记住,一旦您选择了动态/反射路线,您将无法以非类型化操作的方式执行所有操作,直到您返回到编译时已知的类型,或者编译新的类型安全代码以执行(例如,使用
表达式
)更新<代码>hs.添加(x)
。问题是关于不使用
动态
。您的问题仍然不清楚。正如我已经指出的,如果您想要编译时安全(即类型安全),那么您必须在编译时知道类型。
dynamic
类型允许在运行时进行编译,这是解决问题的一种方法。动态构建表达式树是解决此问题的另一种方法(这只是在运行时编译代码的另一种方法)。基本上,任何允许您在运行时编译代码的机制都可以工作,而其他机制则不行。您尝试过什么?提示:除非您使用的是匿名类型,否则不要使用
var
关键字var
与说“我不在乎这是什么类型”(对于那种用法
Object
)是两码事。通过使用
var
您无法立即看到
x
的静态类型是什么。@对于此类问题,Dai是一个很好的建议。。。问题中
x
的类型实际上是
Object
:)什么是
paramX
?为什么
动态
工作?你的问题很具体。到目前为止你试过什么?您是否要记住,一旦您选择了动态/反射路线,您将无法以非类型化操作的方式执行所有操作,直到您返回到编译时已知的类型,或者编译新的类型安全代码以执行(例如,使用
表达式
)更新<代码>hs.添加(x)
。问题是关于不使用
动态
。您的问题仍然不清楚。正如我已经指出的,如果您想要编译时安全(即类型安全),那么您必须在编译时知道类型。
dynamic
类型允许在运行时进行编译,这是解决问题的一种方法。动态构建表达式树是解决此问题的另一种方法(这只是在运行时编译代码的另一种方法)。基本上,任何允许你