Creating a Class Dynamically

How to dynamically create a class?

Yes, you can use System.Reflection.Emit namespace for this. It is not straight forward if you have no experience with it, but it is certainly possible.

Edit: This code might be flawed, but it will give you the general idea and hopefully off to a good start towards the goal.

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace TypeBuilderNamespace
{
public static class MyTypeBuilder
{
public static void CreateNewObject()
{
var myType = CompileResultType();
var myObject = Activator.CreateInstance(myType);
}
public static Type CompileResultType()
{
TypeBuilder tb = GetTypeBuilder();
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

// NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
foreach (var field in yourListOfFields)
CreateProperty(tb, field.FieldName, field.FieldType);

Type objectType = tb.CreateType();
return objectType;
}

private static TypeBuilder GetTypeBuilder()
{
var typeSignature = "MyDynamicType";
var an = new AssemblyName(typeSignature);
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
null);
return tb;
}

private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
ILGenerator getIl = getPropMthdBldr.GetILGenerator();

getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, fieldBuilder);
getIl.Emit(OpCodes.Ret);

MethodBuilder setPropMthdBldr =
tb.DefineMethod("set_" + propertyName,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
null, new[] { propertyType });

ILGenerator setIl = setPropMthdBldr.GetILGenerator();
Label modifyProperty = setIl.DefineLabel();
Label exitSet = setIl.DefineLabel();

setIl.MarkLabel(modifyProperty);
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, fieldBuilder);

setIl.Emit(OpCodes.Nop);
setIl.MarkLabel(exitSet);
setIl.Emit(OpCodes.Ret);

propertyBuilder.SetGetMethod(getPropMthdBldr);
propertyBuilder.SetSetMethod(setPropMthdBldr);
}
}
}

How to Create Java class/es files dynamically?

Working example which will help you.

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

public class HelloWorld {

public static void main(String[] args) throws Exception {

// create an empty source file
File sourceFile = File.createTempFile("Hello", ".java");
sourceFile.deleteOnExit();

// generate the source code, using the source filename as the class name
String classname = sourceFile.getName().split("\\.")[0];
String sourceCode = "public class " + classname + "{ public void hello() { System.out.print(\"Hello world\");}}";

// write the source code into the source file
FileWriter writer = new FileWriter(sourceFile);
writer.write(sourceCode);
writer.close();

// compile the source file
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
File parentDirectory = sourceFile.getParentFile();
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(parentDirectory));
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile));
compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
fileManager.close();

// load the compiled class
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { parentDirectory.toURI().toURL() });
Class<?> helloClass = classLoader.loadClass(classname);

// call a method on the loaded class
Method helloMethod = helloClass.getDeclaredMethod("hello");
helloMethod.invoke(helloClass.newInstance());
}
}

How can I dynamically create derived classes from a base class

This bit of code allows you to create new classes with dynamic
names and parameter names.
The parameter verification in __init__ just does not allow
unknown parameters, if you need other verifications, like
type, or that they are mandatory, just add the logic
there:

class BaseClass(object):
def __init__(self, classtype):
self._type = classtype

def ClassFactory(name, argnames, BaseClass=BaseClass):
def __init__(self, **kwargs):
for key, value in kwargs.items():
# here, the argnames variable is the one passed to the
# ClassFactory call
if key not in argnames:
raise TypeError("Argument %s not valid for %s"
% (key, self.__class__.__name__))
setattr(self, key, value)
BaseClass.__init__(self, name[:-len("Class")])
newclass = type(name, (BaseClass,),{"__init__": __init__})
return newclass

And this works like this, for example:

>>> SpecialClass = ClassFactory("SpecialClass", "a b c".split())
>>> s = SpecialClass(a=2)
>>> s.a
2
>>> s2 = SpecialClass(d=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in __init__
TypeError: Argument d not valid for SpecialClass

I see you are asking for inserting the dynamic names in the naming scope --
now, that is not considered a good practice in Python - you either have
variable names, known at coding time, or data - and names learned in runtime
are more "data" than "variables" -

So, you could just add your classes to a dictionary and use them from there:

name = "SpecialClass"
classes = {}
classes[name] = ClassFactory(name, params)
instance = classes[name](...)

And if your design absolutely needs the names to come in scope,
just do the same, but use the dictionary returned by the globals()
call instead of an arbitrary dictionary:

name = "SpecialClass"
globals()[name] = ClassFactory(name, params)
instance = SpecialClass(...)

(It indeed would be possible for the class factory function to insert the name dynamically on the global scope of the caller - but that is even worse practice, and is not compatible across Python implementations. The way to do that would be to get the caller's execution frame, through sys._getframe(1) and setting the class name in the frame's global dictionary in its f_globals attribute).

update, tl;dr: This answer had become popular, still its very specific to the question body. The general answer on how to
"dynamically create derived classes from a base class"
in Python is a simple call to type passing the new class name, a tuple with the baseclass(es) and the __dict__ body for the new class -like this:

>>> new_class = type("NewClassName", (BaseClass,), {"new_method": lambda self: ...})

update
Anyone needing this should also check the dill project - it claims to be able to pickle and unpickle classes just like pickle does to ordinary objects, and had lived to it in some of my tests.

Creating a class dynamically

A class gains its name when it is assigned to a constant. So It's easy to do in a generic fashion with const_set.

For example, let's say you want to use Struct to build a class with some attributes, you can:

name = "Person"
attributes = [:name, :age]

klass = Object.const_set name, Struct.new(*attributes)
# Now use klass or Person or const_get(name) to refer to your class:
Person.new("John Doe", 42) # => #<struct Person name="John Doe", age=42>

To inherit from another class, replace the Struct.new by Class.new(MyBaseClass), say:

class MyBaseClass; end

klass = Class.new(MyBaseClass) do
ATTRIBUTES = attributes
attr_accessor *ATTRIBUTES
def initialize(*args)
raise ArgumentError, "Too many arguments" if args.size > ATTRIBUTES.size
ATTRIBUTES.zip(args) do |attr, val|
send "#{attr}=", val
end
end
end
Object.const_set name, klass
Person.new("John Doe", 42) # => #<Person:0x007f934a975830 @name="John Doe", @age=42>

Create a dynamic class in java

Just so you know runtime class generation is extremely complex and not something recommended for beginners to the language. This would be an excellent scenario to use a map an anonymous classes.

class AnimalType {
private static final Map<String, Animal> animals = new HashMap<String, Animal>();

static {
// Populating map with default animals
addAnimal("big","BELLOWWWWW"); // bison
addAnimal("small","SQUEEEEEAK"); // mouse
addAnimal("lazy","ROARRRRR"); // lion
addAnimal("loyal","WOOF "); // dog
}

public static void addAnimal(String criteria, final String sound) {
// Assigning a anonymous implementation of animal to the given criteria
animals.put(criteria, new Animal() {
@Override
public void talk() {
System.out.println(sound);
}
});
}

public static Animal getAnimal(String criteria) {
// Returning an animal from the animals map
return animals.get(criteria);
}
}

If you really do insist on true runtime class generation or if you're curious how it works, check out ByteBuddy.



Related Topics



Leave a reply



Submit