web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Dynamics 365 Community / Blogs / Dynamics of Things / a study about Reflection Cl...

a study about Reflection Class for C# programmer

Muhammet ATALAY Profile Picture Muhammet ATALAY 60
Reflection provides objects (of type Type) that describe assemblies, modules and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties ( thanks to Microsoft for the definition  Ref: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection ).

I prepare sort of codes to make Reflection approach closer to you :)

Here are the keywords to be mentioned in the study:
  • Load Assembly, Initiate Class then invoke method(s) with/out parameters - Beginner Level
  • Load Class and Invoke method through Type Def. (string name) with parameters - Beginner Level
  • Suppress cast (convert) operation for incompatible classes with Reflection - Intermediate Level
  • Anonymous Type calls via Reflection - Advance Level

First of all, I would like to describe all classes to be used in the lab. I am going to play with Mathematics mainly Geometry.

IShape.cs : Interface of the shape class.



namespace MathematicsForReflectionScenarios
{
public interface IShape
{
int ColorCode { get; set; }
}
}

Shape.cs : Rests class are going to be inherited from Because, I want to generate bad conversion from one class 2 other class without Reflection.


namespace MathematicsForReflectionScenarios
{
public class Shape : IShape
{
private int colorCode=-1;
public int ColorCode { get { return colorCode; } set { colorCode = value; } }

public int Area()
{
throw new NotImplementedException();
}

public int Perimeter()
{
throw new NotImplementedException();
}
}
}

Rectangle.cs : Operations will take in place.


namespace MathematicsForReflectionScenarios
{
public sealed class Rectangle : Shape
{
int height;
int weight;
public Rectangle()
{

}

public Rectangle(int Height, int Weight)
{
height = Height;
weight = Weight;
}

public new int Area()
{
return height * weight;
}

public new int Perimeter()
{
return 2 * (weight + height);
}

public int customArea(int Height, int Weight)
{
return Height * Weight;
}

public int customPerimeter(int Height, int Weight)
{
return 2 * (Height + Weight);
}
}
}

Square.cs : Operations will take in place.



namespace MathematicsForReflectionScenarios
{
public sealed class Square : Shape
{
int side;
public Square()
{

}

public Square(int Side)
{
side = Side;
}

public new int Area()
{
return side * side;
}
public new int Perimeter()
{
return 4 * side;
}

public int customArea(int Side)
{
return Side * Side;
}

public int customPerimeter(int Side)
{
return 4 * Side;
}
}
}


It was compiled and built so "MathematicsForReflectionScenarios.dll" is generated. 

According to above design, Let's start our journey.

Scenario 1:
- Load library
- Initiate Rectangle class 
- Invoke Method with/out Parameters for Rectangle
- Write the returning value of method to the Console.




 // Load the library from file
Assembly assembly = Assembly.LoadFrom("MathematicsForReflectionScenarios.dll");
MethodInfo methodInfo = null;
object result = null;

//Rectangle
Console.WriteLine("Rectangle ----------");
Type type = assembly.GetType("MathematicsForReflectionScenarios.Rectangle");
if (type != null)
{
// Create a constructor for the Rectangle class.
// Rectangle class already takes two parameters : Height (int) and Width (int) so
// create Type[] array for each parameter seperately
ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(int), typeof(int) });

// Initate the class with 4 and 7
object instance = constructor.Invoke(new object[] { 4, 7 });
try
{
// sample of a method call without parameter
methodInfo = type.GetMethod("Area");
result = methodInfo.Invoke(instance, null);
// Write the result to the output channel
Console.WriteLine("Area Method = " + result.ToString());

// sample of a method call without parameter
methodInfo = type.GetMethod("Perimeter");
result = methodInfo.Invoke(instance, null);
// Write the result to the output channel
Console.WriteLine("Perimeter Method = " + result.ToString());

// sample of a method call with parameter
object[] parametersArray = new object[] { 3, 8 };
methodInfo = type.GetMethod("customArea");
result = methodInfo.Invoke(instance, parametersArray);
// Write the result to the output channel
Console.WriteLine("customArea Method = " + result.ToString());

// sample of a method call with parameter
parametersArray = new object[] { 3, 8 };
methodInfo = type.GetMethod("customPerimeter");
result = methodInfo.Invoke(instance, parametersArray);
// Write the result to the output channel
Console.WriteLine("customPerimeter Method = " + result.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

It is time to make situation complex.
Suppose that we have a method and we send Rectangle class than cast it to the Square which should throw error (Cast mismatch) :)


namespace PlayWithReflection
{
class Program
{
public Shape moveColorCodeTo1 (Shape shape)
{
Assembly assembly = Assembly.LoadFrom("MathematicsForReflectionScenarios.dll");
Type type = assembly.GetType(shape.GetType().ToString());
ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(int), typeof(int) });
object instance = constructor.Invoke(new object[] { 4, 7 });
PropertyInfo propInfo = type.GetProperty("ColorCode");


propInfo.SetValue(instance, 1);

return (Shape)instance;
}
static void Main(string[] args)
{
Program prg = new Program();

Rectangle rec = new Rectangle(1, 2);
rec.ColorCode = 0;
Console.WriteLine("Reflaction : Dynamic Invoke parameter and return objects are different classes Rectangle to Square ----------");
Square s = (Square)prg.moveColorCodeTo3(rec);
Console.WriteLine("Color Code = " + s.ColorCode.ToString());
}
}
}


Let's see how are we going to invoke properties and methods of Anonymous Type. We define Circle type and call methods as well as properties:



namespace PlayWithReflection
{
class Program
{
public object CircleClassOnTheFly()
{
var Circle = new
{
shape = new Shape() ,
radious = -1,
pi = -1,
Area = new Func<int>(() => { return (2 * 4 * 4); }),
Perimeter = new Func<int>(() => { return (2 * 3 * 4); })
};
Assembly assembly = Assembly.LoadFrom("MathematicsForReflectionScenarios.dll");
Type type = Circle.GetType();
ConstructorInfo constructor = type.GetConstructors()[0];
object instance = constructor.Invoke(new object[] { new Shape() { ColorCode = 1 } , 4 , 3, Circle.Area, Circle.Perimeter });

return instance;
}
static void Main(string[] args)
{
Program prg = new Program();

MethodInfo methodInfo = null;
object result = null;
Console.WriteLine("Reflaction : Circle class through generic type ----------");
var genericClass = prg.CircleClassOnTheFly();
type = genericClass.GetType();
foreach(PropertyInfo prop in type.GetProperties())
{
object instanceTemp = prop.GetValue(genericClass);
Type propType = prop.GetValue(genericClass).GetType();

if (propType.GetProperties().Length > 0) // property is a reference to another class or struct
{
foreach (PropertyInfo pInfo in propType.GetProperties())
{
if (pInfo.Name == "Method")
{
methodInfo = (MethodInfo)pInfo.GetValue(instanceTemp);
Func<int> converted = (Func<int>) Delegate.CreateDelegate(pInfo.ReflectedType, null, methodInfo);
Console.WriteLine(prop.Name + " Method = " + converted().ToString());

}
else
if (pInfo.Name != "Target")
Console.WriteLine(pInfo.Name + " = " + pInfo.GetValue(instanceTemp));
}
}
else
{
Console.WriteLine(prop.Name + " = " + prop.GetValue(genericClass).ToString());
}
}
}
}




Here is the source code, download it, debug it, play it !

https://github.com/TheMaty/PlayWithReflection

I do not have any chance to consider the approach from performance perspective. But I will update the article if I have something on that.


Enjoy.





This was originally posted here.

Comments

*This post is locked for comments