This project has moved. For the latest updates, please go here.

How to use CreateInstance(parameters) without passing the type when any one parameter may be null

Jun 27, 2012 at 8:50 AM

Hi Team,

I am using type extension method CreateInstance method to create a constructor instance dynamically.

But according to my requirement, i want to use the method passing only the parameters, but it throws an error (Object reference not set) when any one parameter is null. i wont be knowing the parameter type at compile time.

object[] parameters = new object[2];

  

 

 

parameters[0] = 1;

parameters[1] =null ;

Type type = Assembly.GetExecutingAssembly().GetType("");

 object obj = type.CreateInstance(parameters);

Please help me asap, this is very urgent.

 

 

  

 

 

Coordinator
Jun 27, 2012 at 1:53 PM

I'm afraid that you will have to qualify the parameters array by either providing a separate type array or by associating a name with each parameter.

If you're able to provide parameter types, do something like the following. This avoids Fasterflect calling GetType() on each parameter, and thus avoids the error you are seeing:

    var obj = type.CreateInstance( new [] { typeof(int), typeof(string) }, parameters );

If you're not able to provide types, you can provide Fasterflect with a set of names instead. Fasterflect will attempt to match the named parameters to either constructor parameters or writeable properties (or any combination thereof that causes all parameters to be used):

    var obj = type.TryCreateInstance( new [] { "foo", "bar" }, parameters ); // first parameter is named "foo", second parameter "bar"

Note that the second option is significantly slower as Fasterflect has to determine which (if any) constructor to use.

Jun 27, 2012 at 2:07 PM
Edited Jun 27, 2012 at 2:09 PM

Hi,

 

Thanks for your response, but according to my requirement I will not be knowing which class I need to call as this is obtained on runtime so I won’t be knowing the parameters type.

I want to know how can it determine the parameters having null value and get their parameter types.

 

Below is not feasible for my case:

var obj = type.CreateInstance( new [] { typeof(int), typeof(string) }, parameters );

 

Awaiting for your reply. 

 

Regards,
Praveen Madhogaria

 

Coordinator
Jun 27, 2012 at 5:11 PM
Edited Jun 27, 2012 at 5:12 PM

Fasterflect provides two different strategies to enable you to create objects:

1) Given known types and values, it can invoke the appropriate constructor. This is the CreateInstance method and it has been designed this way in order to offer the best possible performance.

2) Given a set of key-value pairs (either as an anonymous type, a dictionary or a pair of name and value arrays), it can determine the best option for constructing and populating the object. This is the TryCreateInstance method and it has been designed to offer the greatest ease of use possible.

Sadly, there is no third option that allows you to pass in just a set of values. However, you can fairly easily build your own based on the other methods in Fasterflect:

var constructors = type.Constructors().Where( c => c.Parameters().Count == parameters.Length );
foreach( var constructor in constructors )
{
    // TODO: you may wish to optimize this by verifying the constructor parameter types against the actual parameter types
    // if the actual parameter is null, verify that the constructor parameter type is either nullable or a reference type
    try { return constructor.CreateInstance( parameters ); }
    catch( Exception ) /* TODO catch something more specific here once you figure out what exception is thrown */ {}
}
throw new NotSupportedException( "No matching constructor found for the given parameters" );

Hope this helps!

Jun 29, 2012 at 8:28 AM
Edited Jun 29, 2012 at 8:37 AM

Hi Mertner,

 

Thanks again for you response. I have tried with the approach you suggested. My code is as below but the performance is slower using this. Can you suggest what may be the reason.

 

Type[] argumentTypes = new Type[Parameters.Length];
bool flag = false;
var constructors = type.Constructors().Where(c => c.Parameters().Count == Parameters.Length);
foreach (var constructor in constructors)
{
    try
    {
       ParameterInfo[] paraType = constructor.GetParameters();
       for (int j = 0; j < Parameters.Length; j++)
       {
           if (Parameters[j] != null)
           {
                argumentTypes[j] = Parameters[j].GetType();

                if (paraType[j].ParameterType.FullName != "System.Object")
                {
                       flag = paraType[j].ParameterType == argumentTypes[j] ? true : false;
                 }
                 else
                 {
                       flag = true;
                 }
            }
            else
            {
                  if (paraType[j].ParameterType.IsValueType)
                  {
                       flag = (paraType[j].ParameterType.IsGenericType) && (paraType[j].ParameterType.GetGenericTypeDefinition() == typeof(Nullable<>)) ? true : false;
                   }
                   else
                   {
                       flag = true;
                   }
             }
             if (flag == false)
             {
                 break;
             }
      }

      if (flag == true)
      {
           obj = constructor.CreateInstance(Parameters);
           break;
       }
}
catch (Exception e)
{
    throw e;
}

 

 

 

Regards,
Praveen Madhogaria

Coordinator
Jul 1, 2012 at 2:24 PM

Well, you're doing a lot of reflection lookups (querying), which is not something that Fasterflect can speed up.

Generally speaking, you can speed up the code in one of two ways:

1) Reduce the number of reflection lookups

2) Re-think the way you construct your objects, such that can provide more information to Fasterflect and thus be able to use some of the faster methods for constructing objects.