Suppose I have three classes A,B and C generated via emit/reflection abilities of .NET framework, and emmiting object in following manner:
class A
{
B someField1;
C someField2;
}
I need to initialize someField1 and someField2 after creating object:
A someObject;
How to do this? The someObject type is object but I have no idea how to cast it to A type created dynamically and enter fields and initialize it. Thank's in advance for help.
You cannot cast to a dynamically created type in your code, as the compiler cannot know that type.
You can do what you need in a couple of ways:
// 1 - using reflection
// these will actually be your dynamically created objects...
object a = CreateA();
object b = CreateB();
System.Reflection.FieldInfo someField1 = a.GetType().GetField(
"someField1",
BindingFlags.Instance | BindingFlags.NonPublic);
someField1.SetValue(a, b);
or
// 2 - using dynamic (C# 4)
dynamic a = CreateA();
dynamic b = CreateB();
a.someField1 = b;
Just a follow up to Paolo...
If someField1 and someField2 are known at compile time (which appears to be the case) then it would be advisable to have them declared in an interface that your dynamically created class implements. That way you can simply case someObj to the interface type.
interface IObjectWithFields
{
B someField;
C someField;
}
object a = CreateA();
((IObjectWIthFields)a).someField1 = CreateB();
Related
I am facing a really weird behavior of ValueTuple<T1,T2> passed from another assembly, accessed using dynamic. This code under specific circumstances throws RuntimeBinderException at the last line:
TupleTest(out var t);
(dynamic i1, dynamic i2) = t;
dynamic a = i1.Item1;
The message is:
'System.ValueType' does not contain a definition for 'Item1'
TupleTest function is defined in another assembly like this:
static void TupleTest(out ValueTuple<dynamic, dynamic> result) {
result = default;
result.Item1 = (new Priv(), new Priv());
result.Item2 = (new Priv(), new Priv());
}
Where empty class Priv { } has no visibility modifiers.
However, if I add public class Priv, the issue goes away.
I understand, that binder could have had problems accessing instance members of Priv, but in this case I am not getting to that yet! All I am trying to do is to access field Item1 of ValueTuple.
Interestingly, if Priv implements some public interface IFoo, then replacing result.Item1 = (new Priv(), new Priv()); with result.Item1 = ((IFoo)new Priv(), (IFoo)new Priv()) allows dynamic a = i1.Item1 to succeed.
Does that mean, that I can't use dynamic at all to access any public fields, whose value type is private (can only be possible with generics), defined elsewhere?
This happens because Priv is not accessible to the code trying to access it.
The accessibility of the types in dynamic must abide to the compiler rules.
The error message is not very helpful, though.
Code example:
void Foo(params object[] objects)
{
var entries = new List<IEntry>();
foreach(var o in objects)
{
var entry = new Entry<o.GetType()>(); // this doesn't work
entries.Add(entry);
}
...
}
Foo("hello", 5); // should fill entries with Entry<string> and Entry<int>
Why is that not possible? I guess I need to work with reflection instead? How to do that properly AND performant?
You just can't use C# generics the way you're trying to do in your snippet.
In order to use [C#] generics, the actual object type must be known at compile time.
You're trying to dynamically pass the object type as a type parameter. This is simply not possible.
Edit
Yes, it is possible to dynamically create generic objects using reflection. After all, generics is implemented both as a compile-time C# construct and as a .NET framework feature (as opposed to, say, Java, where it is only a compile-time feature based on Type Erasure). So, in .NET, through reflection, it is possible to implement the latter "bypassing" the former (which, again, would be impossible in Java).
But the OP clearly does not need that.
After all, entries is a List<IEntry>. IOW, the entries container does not "know" the concrete type of its elements (since it is bound to an interface). So, if each element to be add already implements IEntry, then this would be enough:
void Foo(params IEntry[] objects)
{
var entries = new List<IEntry>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
OTOH, if those objects do not implement IEntry, then the OP just need a pure, ordinary, old-school list of untyped objects:
void Foo(params object[] objects)
{
var entries = new List<object>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
So using reflection in order to dynamically create a generic container, even if possible, seems to be overkill for this particular use case.
You can do it with reflection
var entryType = typeof(Entry<>);
Type[] typeArgs = { o.GetType() };
var genericType = entryType.MakeGenericType(typeArgs);
IEntry entry = (IEntry)Activator.CreateInstance(genericType);
You need a function of the form:
Func<Type, IEntry>
I would suggest adding a static function to the parent of Foo like this:
public static IEntry Make(Type type)
Inside that function, feel free to add whatever code makes sense to you:
if (type == typeof(string))
{
return new StringEntry(); //Obviously some special logic based on the type.
}
else
{
//Default logic
return (IEntry) Activator.CreateInstance(typeof(Entry<>).MakeGenericType(type));
}
I am attempting to use reflection to enumerate class fields and methods in order to do some automation in a web application. I am also abstracting this so that I could pass in any class.
Is there a way I could somehow pass in the type directly to a function to enumerate on rather than an instance of the type?
I would like the caller side to look like this:
var m = new MyClass(AClassOfSomeTypeIDefined);
I would like to avoid creating an instance as that is misleading to anyone who might use the class (as the instance isn't directly used).
using System;
public void UseType(Type t) {
// do something with t using reflection techniques - e.g.
Console.WriteLine("compat with int? {0}", typeof(int).IsAssignableFrom(t));
}
Call it with C# typeof keyword and the data type you want to pass.
// Examples...
UseType( typeof(int) );
UseType( typeof(System.Int32) );
UseType( typeof(System.Windows.Controls.Button) );
UseType( typeof(IDisposable) );
UseType( typeof(WhateverTypeYouWant) );
System.Type is one of the cornerstones of reflection as you already know, so run with it.
Other notes
Depending on what you want to do with the type, the following peripheral details might be useful.
To create an instance of a Type at runtime without having used the new keyword at compile time, use the System.Activator class. e.g.
// Create a List of strings like: new List<string>();
var list = (List<string>) Activator.CreateInstance( typeof(List<string>) );
yes just use the Type of your class. There's two basic ways to get the type:
Foo foo = new Foo();
Type myType = foo.GetType();
Type myTyp2 = typeof(Foo);
You can use GetType() if you only know the type at runtime (more common with reflection), or typeof() if you know the type at compile time already.
In your example this would be i.e.
var m = new MyClass(typeof(Foo));
You can pass a Type object just like any other parameter.
class MyClass
{
public MyClass(Type yourType)
{
// do as you please with yourType
}
}
The call it:
var m = new MyClass(typeof(YourType));
I am looking for an implementation similar to the type 'id' in objective c which can be of any type during runtime.Is it possible to do that in c#?
let me explain my requirement
id abc;// a common type which can hold any object during runtime
if(cond1)
{
Option1 opt1 = new Option1();//opt1 is an object of user defined class Option1
abc = opt1;
}
else if(cond2)
{
Option2 opt2 = new Option2();
abc = opt2;
}
...
How can I do the same in c# ?
Thanks,
Nikil.
You can do this in two ways:
First, you can declare the type as object. This will allow you to assign anything to the type. Do be aware, however, that if you assign a value type to the object reference, it will be boxed.
For example:
object abc;
if(cond1)
{
Option1 opt1 = new Option1();//opt1 is an object of user defined class Option1
// Assignment works, but you can't call a method or prop. defined on Option1
abc = opt1;
} // ...
The second option, which requires C# 4, is to declare it as dynamic. This will allow you to actually call methods and properties on the object as if it were the "real" type. The method call will fail at runtime if it does not exist, but succeed at compile time.
For example:
dynamic abc;
if(cond1)
{
Option1 opt1 = new Option1();//opt1 is an object of user defined class Option1
// Assignment works
abc = opt1;
// This will work if Option1 has a method Option1Method()!
// If not, it will raise an exception at run time...
abc.Option1Method();
} // ...
dynamic types are exactly for this purpose. Their "type" is dynamic(which obviously means at run-time).
I don't know about objective-C but it seems like id = dynamic.
Essentially a dynamic type is treated as a "typeless" object. There is no intellisense and no type checking done at compile time.
object abc; // :-)
or is it too simple?
You have several choices to consider and var isn't one of them.
1) Make all you Option classes inherit from an abstract base class.
2) Make all your Option classes inherit from an Interface.
3) Use object as the type
4) Use a dynamic object
It depends on what you want to do with 'abc' after this point in the code.
Declare an object or use the dynamic keyword as others say, or if you know an interface or base class that all your possible objects derive from, use that type:
IOption abc;
Let's say I have a Type called type.
I want to determine if I can do this with my type (without actually doing this to each type):
If type is System.Windows.Point then I could do this:
Point point1 = new Point();
However if type is System.Environment then this will not fly:
Environment environment1 = new Environment(); //wrong
So if I am iterating through every visible type in an assembly how do I skip all the types that will fail to create an instance like the second one? I'm kind of new to reflection so I'm not that great with the terminology yet. Hopefully what I'm trying to do here is pretty clear.
static classes are declared abstract and sealed at the IL level. So, you can check IsAbstract property to handle both abstract classes and static classes in one go (for your use case).
However, abstract classes are not the only types you can't instantiate directly. You should check for things like interfaces (without the CoClass attribute) and types that don't have a constructor accessible by the calling code.
type.IsAbstract && type.IsSealed
This would be a sufficient check for C# since an abstract class cannot be sealed or static in C#. However, you'll need to be careful when dealing with CLR types from other languages.
you can search for public contructors like this,
Type t = typeof(Environment);
var c = t.GetConstructors(BindingFlags.Public);
if (!t.IsAbstract && c.Length > 0)
{
//You can create instance
}
Or if you only interested in parameterless constructor you can use
Type t = typeof(Environment);
var c = t.GetConstructor(Type.EmptyTypes);
if (c != null && c.IsPublic && !t.IsAbstract )
{
//You can create instance
}
Type t = typeof(System.GC);
Console.WriteLine(t.Attributes);
TypeAttributes attribForStaticClass = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass | TypeAttributes.Class |
TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit;
Console.WriteLine((t.Attributes == attribForStaticClass));
I guess, this should work.
This is a way to get all public contstuctors of all types in an assembly.
var assembly = AppDomain.CurrentDomain.GetAssemblies()[0]; // first assembly for demo purposes
var types = assembly.GetTypes();
foreach (var type in types)
{
var constructors = type.GetConstructors();
}