English 中文(简体)
How to generate an instance of an unknown type at runtime?
原标题:

i ve got the following in C#:

string typename = "System.Int32";
string value = "4";

theses two strings should be taken to generate an object of the specified type with the specified value...

result should be:

object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;
最佳回答

Is this what are you are thinking?

object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
问题回答

As stated, this is too broad and can not be solved generally.

Here are some options:

Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type);

This will create an instance of the type that typename is describing. It calls the parameterless constructor of that type. (Downside: Not all objects have a parameterless constructor. Further, this does set the state of the object using value.)

Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type, new[] { value });

This will create an instance of the type that typename is describing. It calls a constructor of that type that accepts one parameter of type string. (Downside: Not all objects have such a constructor. For example, Int32 does not have such a constructor so you will experience a runtime exception.)

Type type = Type.GetType(typename);
object o = Convert.ChangeType(value, type);

This will attempt to convert the string value to an instance of the required type. This can lead to InvalidCastExceptions though. For example, Convert.ChangeType("4", typeof(FileStream)) will obviously fail, as it should.

In fact, this last example (create an instance of type FileStream with its initial state determined by the string "4") shows how absurd the general problem is. There are some constructions/conversions that just can not be done.

You might want to rethink the problem you are trying to solve to avoid this morass.

Creating an instance of a type you know by name (and which should have a default constructor):

   string typeName = "System.Int32";
   Type type = Type.GetType(type);
   object o = Activator.CreateInstance(type);

Parsing a value from a string will obviously only work for a limited set of types. You could

  • use Convert.ChangeType as suggested by PhilipW
  • or maybe create a Dictionary<Type,Func<string,object>> which maps known types to known parse functions
  • or use reflection to invoke the Parse(string) method on the type, assuming there is one:

       string valueText = "4";
       MethodInfo parseMethod = type.GetMethod("Parse");
       object value = parseMethod.Invoke(null, new object[] { valueText });
    
  • or maybe you can use the infrastructure provided by the .NET component model. You can fetch the type converter of a component and use it like this:

       TypeConverter converter = TypeDescriptor.GetConverter(type);
       object value = converter.ConvertFromString(valueText);
    

Your logic seems a little flawed here. Obviously, if you re directly casting the object at a later time to the actual type it is, then you must know the type to begin with.

If there s something else that is missing from this question please elaborate and maybe there is a more appropriate answer than simply, "This doesn t make much sense."

Perhaps you have a set of different types, all of which implement a known interface?

For example if you have several different user controls and want to load one of them into a container, each one might implement IMyWobblyControl (a known interface) yet you might not know until runtime which of them to load, possibly from reading strings from some form of configuration file.

In that case, you ll need to use reflection to load the actual type from something like the full assembly name, then cast it into your known type to use it.

Of course, you need to make sure that your code handles invalid cast, assembly not found and any of the other exceptions that are likely to come along through something as wobbly as this...

This seems like a job for Int32.Parse(string). But to agree with the others it seems this is "unique" and one should probably think gloves.

Here s a specific example of the problem involving Azure SQL Federations...which splits data into separate db s according to a key range.

The key range types are:

SQL / .Net SQL type / CLR .Net

INT / SqlInt32 / Int32, Nullable

BIGINT / SqlInt64 / Int64, Nullable

UNIQUEIDENTIFIER / SqlGuid /Guid, Nullable

VARBINARY(n), max n 900 / SqlBytes, SqlBinary /Byte[]

Ideally, a C# function param could take either .Net SQL type or CLR .Net type but settling on just one category of type is fine.

Would an "object" type param be the way to go? And, is there a feasible way to identify the type and convert it accordingly?

The concept is something like:

public void fn(object obj, string fedName, string distName, bool filteringOn)

{

...figure out what type obj is to ensure it is one of the acceptable types...

string key = obj.toString();

return string.Format("USE FEDERATION {0} ({1}= {2} ) WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn ? "ON" : "OFF"));

}

Though the param value is cast to string, it will be recast/checked on the sql server side so validating it on the app side is desired.

After using:

Type type = Type.GetType(typename);

Try this extension method:

public static class ReflectionExtensions
{
    public static T CreateInstance<T>(this Type source, params object[] objects)
        where T : class
    {            
        var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray());
        return cons == null ? null : (T)cons.Invoke(objects);
    }
}

Hope this helps.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签