using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;
using System.IO;
using System.Web;
namespace PK.Utilities.Reflection
{
public class Reflector
{
private delegate T ObjectActivator(params object[] args);
///
/// Create an instance from an object using reflection and linq expressions. Works for every constructor
///
/// The type of the object to instance
/// The name of the assembly who stores the type
/// The fullname of the type to instanciate
/// The arguments of the constructor
/// An instance of the given type
public static T GetInstance(string assemblyName, string typeFullName, params object[] args)
{
T res = default(T);
//var completeAssemblyName =Path.Combine(GetRunningPath(), assemblyName + (assemblyName.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) ? "" : ".dll"));
Assembly assembly = Assembly.Load(GetAssemblyName(assemblyName));
Type type = assembly.GetType(typeFullName);
ConstructorInfo ctor = GetConstructor(args, type);
ObjectActivator createdActivator = GetActivator(ctor);
res = createdActivator(args);
return res;
}
private static AssemblyName GetAssemblyName(string assemblyName)
{
var name = new AssemblyName(assemblyName);
return name;
}
private static ConstructorInfo GetConstructor(object[] args, Type type)
{
if (args == null)
args = new object[0];
ConstructorInfo ctor = type.GetConstructor(args.Select(o => o.GetType()).ToArray());
return ctor;
}
///
/// Create an instance from an object using reflection and linq expressions. Works for every constructor
///
/// The type of the object to instance
/// A Type object containing the object type to instantiate
/// The arguments of the constructor
/// An instance of the given type
public static T GetInstance(Type type, params object[] args)
{
T res = default(T);
ConstructorInfo ctor = GetConstructor(args, type);
ObjectActivator createdActivator = GetActivator(ctor);
res = createdActivator(args);
return res;
}
///
/// Create an instance from an object using reflection and linq expressions. Uses the default constructor.
///
/// The type of the object to instance
/// The name of the assembly who stores the type
/// The fullname of the type to instanciate
/// An instance of the given type
public static T GetInstance(string assemblyName, string typeFullName)
{
return GetInstance(assemblyName, typeFullName, new object[] { });
}
///
/// Create an instance from an object using reflection and linq expressions. Uses the default constructor.
///
/// The type of the object to instance
/// The string with full type name and asembly, in format "fullName, Assembly"
/// An instance of the given type
public static T GetInstance(string fullTypeName)
{
var values = fullTypeName.Split(new char[]{','}, 2 );
return GetInstance(values[1].Trim(), values[0].Trim(), new object[] { });
}
///
/// Creates an ObjectActivator specifyc for an object type and a constructor type
///
/// Type of the object to get an instance for
/// ContructorInfo containing detail information for an specicyc contrustor
/// An delegate of the compiled ObjectActivator method
private static ObjectActivator GetActivator(ConstructorInfo ctor)
{
ParameterInfo[] paramsInfo = ctor.GetParameters();
//create a single param of type object[]
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
//pick each arg from the params array
//and create a typed expression of them
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
//make a NewExpression that calls the
//ctor with the args we just created
NewExpression newExp = Expression.New(ctor, argsExp);
//create a lambda with the New
//Expression as body and our param object[] as arg
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);
//compile it
ObjectActivator compiled = (ObjectActivator)lambda.Compile();
return compiled;
}
}
}