Answered by:
Reflection - Creating class at runtime throwing error

Question
-
User-1343058805 posted
Hi All,
I have a abstract class and bunch of concrete classes implementing the abstract class. This scenario is working fine in normal class creation but requirement has changed. As per new requirement concrete class should be generated at runtime, I am using following code:
namespace NSUser.Entity
{
public abstract class testApprover
{protected testApprover nextLevel;
public int UserID { get; set; }
public string UserName { get; set; }public testApprover()
{ }public void SetNextLevel(testApprover nLevel)
{
this.nextLevel= nLevel;
}public virtual string ProcessQuery(Job job, enumAction action)
{
......
}
}public AssemblyBuilder CreateObject()
{
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "DynamicReflect";
AppDomain thisDomain = AppDomain.CurrentDomain;
asmBuilder = thisDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
modBuilder = asmBuilder.DefineDynamicModule(asmBuilder.GetName().Name, "DynamicLib.dll");
TypeBuilder typeBuilder = null;
DataSet ds = createTable();
Type generetedType = null;
string cName = null;
foreach (DataRow dr in ds.Tables[0].Rows) //class names are coming from database
{
cName = dr["WFClassName"].ToString();
var classType = new CodeTypeDeclaration(dr[0].ToString());
classType.Attributes = MemberAttributes.Public;
classType.BaseTypes.Add("NSUser.Entity.testApprover");typeBuilder = modBuilder.DefineType(dr[0].ToString(),
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
typeof(NSUser.Entity.testApprover),null);Type[] ctorParams = new Type[] {};
generetedType = typeBuilder.CreateType();
}
foreach (DataRow dr in ds.Tables[0].Rows)
{
Type _typeName = asmBuilder.GetType(dr["WFClassName"].ToString());
object ptInstance = Activator.CreateInstance(_typeName);
((testApprover)ptInstance).UserName = "test";
PropertyInfo prop = _typeName.GetProperty("UserName");
prop.SetValue(((testApprover)ptInstance).UserName, "test");
THROWING FOLLOWING ERROR:
An unhandled exception of type 'System.Reflection.TargetException' occurred in mscorlib.dll
Additional information: Object does not match target type.
}
return asmBuilder;
}Goal is to create a following concrete class
namespace NSUser.Entity
{
class Initiator : testApprover
{
}
}testApprover _initiator = new Initiator() { UserName = "testuser" };
Please let me know how to resolve/achieve this using reflection.
Thanks
Sham
Friday, October 16, 2015 7:53 AM
Answers
-
User-1343058805 posted
Hi All,
Thanks a lot for all your help, I am stuck at final step. How to invoke SetNextLevel method from created instance on above code.
Type _typeName = asmBuilder.GetType(dr["WFClassName"].ToString());
object ptInstance = Activator.CreateInstance(_typeName);-- nextLevel is protected, when I do following assignment returning ERROR
((testApprover)ptInstance ).SetNextLevel ="new class instance"
Cannot assign to 'SetNextLevel' because it is a 'method group' <-- ERRORThanks
Sham- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, November 2, 2015 9:40 AM
All replies
-
User-1343058805 posted
After making some changes, receiving following error.
Additional information: Non-static method requires a target.
Please let me know how to resolve.
Sunday, October 18, 2015 10:29 PM -
User-219423983 posted
Hi sham,
About the error “Object does not match target type”, you should just replace
prop.SetValue(((testApprover)ptInstance).UserName, "test");
with
prop.SetValue(((testApprover)ptInstance), "test");
in your code. According to the following link, the first parameter represents an object whose property value will be set. So, here it should be an instance of a class.
https://msdn.microsoft.com/en-us/library/hh194291(v=vs.110).aspx
In your latest reply, you got error “Non-static method requires a target“, could you show which line happens the error and what did you change?
I hope it’s useful to you.
Best Regard,
Weibo Zhang
Monday, October 19, 2015 10:36 PM -
User-1343058805 posted
Hi Zhang,
Thanks for your input, it worked I am able to assign the properties for each object coming from the database.
Currently I have configuration to create 3 classes dynamically (above code) and returning created assembly to the caller.
RuntimeObject runObj = new RuntimeObject();
AssemblyBuilder runObject = runObj.CreateObject(); <--- returning above created assembly --->I do see all classes created previously in runObject, when I try to access one of the class property getting following error:
((testApprover)runObject.GetTypes()[0]).UserName
Cannot convert type 'System.Type' to 'NSUser.Entity.testApprover'Thanks
Sham
Tuesday, October 20, 2015 4:46 PM -
User-1343058805 posted
Storing instance of each class in a list resolve the issue.
Thanks for the help. Greatly appreciate for the time spent to answer my question.
Tuesday, October 20, 2015 10:33 PM -
User-1343058805 posted
Hi All,
Thanks a lot for all your help, I am stuck at final step. How to invoke SetNextLevel method from created instance on above code.
Type _typeName = asmBuilder.GetType(dr["WFClassName"].ToString());
object ptInstance = Activator.CreateInstance(_typeName);-- nextLevel is protected, when I do following assignment returning ERROR
((testApprover)ptInstance ).SetNextLevel ="new class instance"
Cannot assign to 'SetNextLevel' because it is a 'method group' <-- ERRORThanks
Sham- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, November 2, 2015 9:40 AM