I have a follwing class structure:
public abstract class AbstractFoo
{
public virtual void Prepare()
{
}
}
public class Foo : AbstractFoo
{
public override void Prepare()
{
}
}
public class Bar : Foo
{
public override void Prepare()
{
}
}
public class ClassThatUses
{
public Foo Foo;
}
var classThatUsesInstance = new ClassThatUses { Foo = new Bar (); }
Somehow in ClassThatUses i need to call (through the reflection - mandatory) Prepare method of the class Bar.
Instead of question (???) marks i need to make a reflection code that will call the Prepare method of Bar rather than foo.
Basically, it should be something like:
classThatUsesInstance.GetType.GetProperties()[0]
-> somehow understand that it's actually Bar, but not Foo.
-> call method (which i know how to do, i just need the RIGHT method to be used)
I don't know whether it's Bar, or BarBar, or BarBarBar. I need to find out the REAL type of assigned field rather then type it was casted to.
Is this any possible?
Or is it at least possible to find out the real type of the Foo field in runtime?
p.s. i realize that without reflection it will be called - no problem. this is more of a theory.
UPD: http://msdn.microsoft.com/en-us/library/a89hcwhh.aspx
Note that you cannot use the MethodInfo object from the base class to invoke the overridden method in the derived class, because late binding cannot resolve overrides.
Does that mean the problem is unsolvable?
The GetType method will give you the real type of Foo at runtime:
public class ClassThatUses
{
public Foo Foo { get; set; }
public void CallPrepare()
{
// Foo.Prepare();
Foo.GetType().GetMethod("Prepare").Invoke(Foo, null);
}
}
Following your edit, if you want to find the runtime type of Foo for a particular instance of ClassThatUses then you'll need to use GetValue to interrogate the value of Foo on that instance:
ClassThatUses o = new ClassThatUses() { Foo = new Bar() };
// Type fooType = o.Foo.GetType();
Type fooType = o.GetType().GetProperty("Foo").GetValue(o, null).GetType();
typeof(Bar).GetMethod("Prepare").Invoke(foo, new object[] { });
or
foo.GetType().GetMethod("Prepare").Invoke(foo, new object[] { });
is it at least possible to find out
the real type of the Foo field in
runtime?
Yes, with foo.GetType()
Related
Apologies if this is duplicate, I'm not familiar enough with the correct terminology to know if this is asked elsewhere. I'm new to interfaces and am creating some sample code to see what kind of helpful things they can achieve.
I have a method that returns two possible classes that both implement the same interface. However, I can only access the properties from the parent class and not the sub-class, and have failed to find an explanation. I realise my entire approach may be flawed and will accept that advise also.
This is better explained with an example (NetFiddle) and questions...
using System;
public interface IAb
{
int Prop1 { get; set; }
}
public class A : IAb
{
public int Prop1 { get; set; }
}
public class B : A, IAb
{
public string Prop2 { get; set; }
}
public class Program
{
static class MyMethods
{
public static IAb CreateObject(Type t)
{
if (t == typeof(A))
{
return new A() {Prop1 = 123};
}
else
{
return new B() {Prop1 = 456, Prop2 = "Foo"};
}
}
}
public void Main()
{
IAb AorB = MyMethods.CreateObject(typeof(B));
Console.WriteLine(AorB.Prop1);
if (AorB is B)
{
// fails
// Console.WriteLine((B)AorB.Prop2); // 'IAb' does not contain a definition for 'Prop2'
// works
B newVar = (B)AorB;
Console.WriteLine(newVar.Prop2);
}
}
}
Based on the above:
Why does AorB.Prop1 work, but not AorB.Prop2 without an explicit cast?
Does the above mean that an interface should always be cast to a class before reading it's properties?
Is there a better way to specify the return type of the example method? The current approach feels error-prone because this (albeit unlikely code) would cause an error: var AorB = (B) MyMethods.CreateObject(typeof(A));
You may use pattern matching with is operator to make it more clear
IAb AorB = MyMethods.CreateObject(typeof(B));
Console.WriteLine(AorB.Prop1);
if (AorB is B b)
{
Console.WriteLine(b.Prop2);
}
Your failed line becomes correct after using right parenthesis
Console.WriteLine(((B)AorB).Prop2);
There is also no need to inherit B class from both A class and IAB interface. Since A already implements IAB, you can simply use public class B : A
Is there a better way to specify the return type of the example
method?
Make the CreateObject method generic and use constraints to restrict T type parameter to class, which implements IAb interface and has a parameterless constructor (this's what new() means exactly)
public static T CreateObject<T>() where T : IAb, new()
{
return new T { Prop1 = 123 };
}
and invoke it in the following way
IAb AorB = MyMethods.CreateObject<B>();
But in this case you can set only properties, defined in IAb interface, not the B class specific.
Why does AorB.Prop1 work, but not AorB.Prop2 without an explicit cast?
Because the property selector has precedence over the type cast. Just add parentheses:
Console.WriteLine(((B)AorB).Prop2);
Does the above mean that an interface should always be cast to a class before reading it's properties?
No.
Is there a better way to specify the return type of the example method? The current approach feels error-prone because this (albeit unlikely code) would cause an error: var AorB = (B) MyMethods.CreateObject(typeof(A));
You could use generics:
T CreateObject<T>() where T : new()
{
return new T();
}
However, that does not provide you with compile-time access to properties as in your example. You could slightly improve by providing versions of the method with appropriate constraints:
T CreateObject<T>() where T : IAb, new()
{
var result = new T();
result.Prop1 = 123;
return result;
}
Consider the following class
class Foo
{
public Foo(IBar bar=null)
{
}
}
I have a need to inject an alternate constructor to allow the IBar instance to be provided on demand rather than injected.
class Foo
{
public Foo(IBar bar=null)
{
}
public Foo(Func<IBar> barFunc) : this((IBar)null)
{
}
}
However there is a bunch of code in several dependent projects like:
Foo foo = new Foo(null);
This code won't compile anymore due to the ambiguous constructor reference.
Obviously I could change the code to
Foo foo = new Foo((IBar)null);
But this would require changes to a whole bunch of projects, and my goal is a transparent change. Is there some way to specify which constructor to call if ambiguous? Or a way to indicate to the compiler that barFunc cannot be null
At the moment, I am looking at this but it feels .... dirty
class Foo
{
public Foo(IBar bar=null)
{
}
public Foo(Func<IBar> barFunc, bool notUsed) : this((IBar)null)
{
}
}
Maybe use a static method ala named constructor idiom:
class Foo
{
...
public static Foo Create(Func<IBar> func)
{
return new Foo(func());
}
}
Make the Foo(Func<IBar>) constructor private, and add a factory method:
public static Foo WithIBarFunc(Func<IBar> func) {
return new Foo(func);
}
If you can, delete the the Foo(Func<IBar>) constructor all together and write the method like this:
public static Foo WithIBarFunc(Func<IBar> func) {
var foo = new Foo(null);
// initialise foo with func...
return foo;
}
I have the following interfaces and concrete implementations:
interface IFoo {
string Name { get ;}
}
class Foo :IFoo{
public string Name { get; set; }
}
interface IBar {
string Name { get; }
}
class Bar : IBar {
public string Name { get;set;}
public Bar(Foo foo) {
}
}
You can see that Bar has a dependency on Foo in the class constructor.
These are my bindings:
kernel.Bind<IFoo>().ToConstant(new Foo() { Name="Foo"; });
kernel.Bind<IBar>().To<Bar>();
When I use kernel.Get and ask for Bar, there are no errors, but the Foo dependency is a different instance of Foo that I originally bound. I expected to see Foo with a name of "Foo" when I inspect the Foo instance inside of the Bar constructor, but instead I see Foo { Name = null }.
When I bind to concrete Foo, everything works as expected:
var foo = new Foo() { Name="Foo" };
kernel.Bind<IFoo>().ToConstant(foo);
kernel.Bind<Foo>().ToConstant(foo);
kernel.Bind<IBar>().To<Bar>();
var bar= kernel.Get<Bar>(); // works! foo has name "Foo"
Is there a convenient way to bind a specific instance of Foo to all the available interfaces, and concrete types?
For example:
class ConcreteFoo : AbstractFoo, IFoo {
...
}
var foo = new Foo();
kernel.Bind<IFoo>().ToConstant(foo);
kernel.Bind<AbstractFoo>().ToConstant(foo);
kernel.Bind<ConcreteFoo>().ToConstant(foo);
I have a generic framework. Outside of the framework is Foo and Bar that the clients define. I want clients to have the flexibility of specifying IFoo or Foo in the Bar constructor. If the constructor was defined as Bar(IFoo), the client might be casting it to Foo anyway.
There's no such functionality provided by ninject. What ninject offers is binding to multiple types, for example:
Bind<IFoo,Foo>().To<Foo>().InSingletonScope();
Ensures no matter what combination of IFoo and Foo are requested, you always get the same Foo instance.
Then, there's Ninject.Extensions.Conventions which can look for types (like all classes of an assembly) and bind them to all their interface, all their base types,... but only either or, not both. You could use this to achieve what you want, but it would require quite some code on your end, too,.. and it would be kind of akward.
So, in my opinion, it's best just to roll your own:
using Ninject.Infrastructure.Language;
public static void RegisterConstantAsAllTypes(IBindingRoot bindingRoot, object instance)
{
Type t = instance.GetType();
IEnumerable<Type> typesToBind = t.GetAllBaseTypes()
.Concat(t.GetInterfaces())
.Except(new[] { typeof(object) });
bindingRoot
.Bind(typesToBind.ToArray())
.ToConstant(instance);
}
Given your example the following test passes:
[Fact]
public void FactMethodName()
{
var kernel = new StandardKernel();
var foo = new Foo();
RegisterConstantAsAllTypes(kernel, foo);
kernel.Get<IFoo>().Should().Be(foo);
kernel.Get<Foo>().Should().Be(foo);
kernel.Get<AbstractFoo>().Should().Be(foo);
}
I've created a class in C# which uses the method "Action".
public void Action()
{
}
The method is empty because, when a new instance of the class is created, the user should be able to define what the method does. One user may need the method to write to the console, another may want it to assign a value to a variable, etc. Is there any way for me to change what the method can do outside of its original definition, along the lines of the following:
//Using the instance "MyClass1", I have assigned a new action to it (Writing to the console)
//Now the method will write to the console when it is called
MyClass1.Action() = (Console.WriteLine("Action"));
Is there any way for me to change what the method can do outside of
its original definition
Not via "Named Methods" and the way you're using them in your example. If you want your class to be able to invoke a unit of execution defined by the user, you need to look either into inheritance hierarchy (as specified in #CodeCaster answer via virtual methods and overriding them), or perhaps look into delegates.
You can use an Action delegate:
public Action Action { get; set; }
Use it like so:
var class = new Class();
class.Action = () => { /*Code*/ }
And, when you want to invoke it:
if (class.Action != null)
{
class.Action();
}
By making it abstract, inheriting the class and overriding the method.
public class FooBase
{
public abstract void Bar();
}
public class Foo1 : FooBase
{
public override void Bar()
{
// Do something
}
}
public class Foo2 : FooBase
{
public override void Bar()
{
// Do something else
}
}
Suppose I have some generic class foo
public class foo<SomeType>
{
public SomeType x;
public foo () {
}
}
And a class bar that is derived from foo
public class bar : foo <SomeType>
{
public bar
{
}
}
What I'd like to do is pass SomeType to the base class when I create a bar object. How do I go about doing this?
Clarification: As an example, what I would like to do is create an object of type bar and tell it that the type of the variable x in foo is, say, an integer. What i want to pass is not an instance of SomeType, but rather what SomeType actually is (an int, string, etc..).
If you want to make bar generic you need to add a type parameter:
public class bar<T> : foo<T>
{
public bar() { ... }
}
Declare bar as follows:
public class bar<SomeType> : foo <SomeType>
And later instantiate it this way:
new bar<X>();
Are you looking for this construct, which makes clear that Bar is also paraameterized by <SomeType>?
public class bar<SomeType> : foo <SomeType>
{
public bar()
{
// Code here
}
}