我有从基类派生的类,并希望在运行时动态实例化这些类。使用以下代码,我可以使用默认构造函数构建一个类:
public abstract class Employee : IEmployeeInterface
{
public string Name { get; set; }
public Employee() { }
public Employee(string name)
{
Name = name;
}
}
public static class EmployeeBot
{
static readonly Func<string, Func<Employee>> EmployeeBotFunction = x =>
Expression.Lambda<Func<Employee>>(
Expression.New(Type.GetType(x).GetConstructor(Type.EmptyTypes))
).Compile();
public static Employee InstantiateNewEmployee(string type)
{
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
return EmployeeBotFunction(argumentType).Invoke();
}
}
Worker
实现了Employee
,可以使用以下方式创建:
Employee employee = EmployeeBot.InstantiateNewEmployee("Worker");
然后,由于Worker
具有与Employee
完全相同的方法,因此调用它们将按预期从工人类中提供结果。
但是,我无法弄清楚如何正确实现类似的代码来使用带参数的构造函数。例如:
static readonly Func<string, Type[], Func<string, Employee>> NewEmployee = (x, y) =>
Expression.Lambda<Func<string, Employee>>(
Expression.New(Type.GetType(x).GetConstructor(y))
).Compile();
public static Employee InstantiateNewEmployee(string type, string Name)
{
Type[] construct = new Type[] { typeof(string) };
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
return NewEmployee(argumentType, construct).Invoke(Name);
}
调用此方法会抛出异常:
EmployeesTests.InstantiateEmployeeWithName抛出异常: System.InvalidOperationException:只能在Type上调用Method Type.IsGenericParameter为true。
如何更改NewEmployee
函数以接受第二个构造函数所需的参数?
答案 0 :(得分:1)
我已经在@JSteward的帮助下回答了这个问题,谢谢!
结合不同版本的public class Worker : Employee
并修复了一个愚蠢的错误,我能够解决这个问题。你不能实例化一个抽象类,所以我的构造函数应该在一个派生类上,例如public abstract class Employee
而不是Expression.New(Type.GetType(x).GetConstructor(y));
。
实际错误是null
的构造函数参数是static readonly Func<string, Type[], ParameterExpression[], Func<string, Employee>> NewEmployee = (x, y, z) =>
Expression.Lambda<Func<string, Employee>>(
Expression.New(Type.GetType(x).GetConstructor(y), z)
, z).Compile();
public static Employee InstantiateNewEmployee(string type, string Name)
{
Type[] construct = new Type[] { typeof(string) };
string argumentType = string.Format("{1}.{0}", type.ToString(), MethodBase.GetCurrentMethod().DeclaringType.Namespace);
ParameterExpression[] arguments = new ParameterExpression[] { Expression.Parameter(typeof(string)) };
return NewEmployee(argumentType, construct, arguments).Invoke(Name);
}
,因为它没有在Worker上定义。
第二个例子现在变成了; (虽然我确信这可以改进!)。
def likeMovement(pID):
print("Give a rating for the movement with #id:%s" %pID)
rate=input("Give from 0-5: ")
userID=str(1)
print(rate,type(rate))
print(pID,type(pID))
print(userID,type(userID))
cursor=con.cursor()
sqlquery='''UDPATE likesartmovement SET likesartmovement.rating=%s WHERE
likesartmovement.artisticID=? AND likesartmovement.userID=?''' % (rate,),
(pID,userID)
cursor.execute(sqlquery)
@JSteward评论的帖子实际上已经概括了这个要求:linq-expressions-creating-objects
感谢您的帮助以及博客的评论。
但很高兴看到我并不是唯一一个疯狂地以这种方式使用表达式的人!