I'm writing a program that would have the possibility to learn for itself.
Example:
- a word 'day' was typed
- look for interface named 'day'
- does it exists?
- No => create class based on that interface (and implement the interface) and save it for next use then create instance of that class
- Yes => create instance of that class
Google gave me this: How to dynamically create a class in C#?
This solution is the closest I can think of for my scenario, but it assumes you already know how many properties you will need and doesn't implement an interface at all.
I have no experience at all with system.reflection but I'm eager to learn!
Anyone know an example for my case?
Any help is appriciated.
Thank You!
EDIT: MY SOLUTION (Because nobody gave me a straight answer I figured it out myself)
public void createObject(string name)
{
//Namespace where the interfaces are located
string strnamespace = "Intelligence.Omnia.Categories";
//Get interfacecollection
List<Type> interfaceCollection = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsInterface && t.Namespace == strnamespace).ToList();
foreach (Type myinterface in interfaceCollection)
{
//interface names
List<string> interfaceNames = new List<string>();
if (myinterface.Name == name)
{
//Add interface name
interfaceNames.Add(myinterface.Name);
//Add current interfaceproperties
List<PropertyInfo> myProps = myinterface.GetProperties().ToList();
//Does the current interface inhiretes from other interfaces?
foreach (Type inhiretences in myinterface.GetInterfaces())
{
//Add interface name
interfaceNames.Add(inhiretences.Name);
//Add those properties aswell!
foreach (PropertyInfo pi in inhiretences.GetProperties())
{
myProps.Add(pi);
}
}
createType(name, myProps, interfaceNames);
}
}
}
static void createType(string name, List<PropertyInfo> props, List<string> interfacesnames)
{
//create instance of CSharpCodeProvider
CSharpCodeProvider csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
//DLL
string pathDLL = AppDomain.CurrentDomain.BaseDirectory + "Objects.dll";
CompilerParameters parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.dll", "System.Linq.dll", "System.Threading.Tasks.dll", "Intelligence.dll" });
parameters.OutputAssembly = pathDLL;
parameters.GenerateExecutable = false;
ICodeCompiler icc = csc.CreateCompiler();
//>>>>Generated CODE
//Add namespaces
CodeCompileUnit compileUnit = new CodeCompileUnit();
CodeNamespace ns = new CodeNamespace("Objects");
compileUnit.Namespaces.Add(ns);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
ns.Imports.Add(new CodeNamespaceImport("System.Linq"));
ns.Imports.Add(new CodeNamespaceImport("System.Text"));
ns.Imports.Add(new CodeNamespaceImport("System.Threading.Tasks"));
ns.Imports.Add(new CodeNamespaceImport("Intelligence"));
ns.Imports.Add(new CodeNamespaceImport("Intelligence.Omnia"));
ns.Imports.Add(new CodeNamespaceImport("Intelligence.Omnia.Categories"));
//Define your class
CodeTypeDeclaration classType = new CodeTypeDeclaration("Object"+name);
classType.Attributes = MemberAttributes.Public; //make it public
foreach(string interfaceName in interfacesnames) //let it inherit from the interfaces
{
classType.BaseTypes.Add(interfaceName);
}
ns.Types.Add(classType);
//Add constructor
CodeConstructor constr = new CodeConstructor();
constr.Attributes = MemberAttributes.Public;
classType.Members.Add(constr);
//Add all the properties
foreach (var prop in props)
{
//If you want private fields
//CodeMemberField field = new CodeMemberField(prop.PropertyType, prop.Name);
//classType.Members.Add(field);
CodeMemberProperty property = new CodeMemberProperty();
property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
property.Type = new CodeTypeReference(prop.PropertyType);
property.Name = prop.Name;
property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), prop.Name)));
property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), prop.Name), new CodePropertySetValueReferenceExpression()));
classType.Members.Add(property);
}
//Write the file for later use
TextWriter tw = new StreamWriter(new FileStream(AppDomain.CurrentDomain.BaseDirectory + "Objects\\" + name + ".cs", FileMode.Create));
csc.GenerateCodeFromCompileUnit(compileUnit, tw, null);
tw.Close();
//Compile the class
CompilerResults results = icc.CompileAssemblyFromFile(parameters, AppDomain.CurrentDomain.BaseDirectory + "Objects\\" + name + ".cs");
results.Errors.Cast<CompilerError>().ToList().ForEach(error => System.Windows.Forms.MessageBox.Show(error.ErrorText));
}