So, this might seem similar to other issues with the same title out there - but I couldn't find a solution to the specific issue i'm having. Please feel free to link a solution if there's one already out there.
Background:
I have this method which needs to accept a generic interface as a parameter type (as other objects also need to call this function)
I have simplified the problem to not include the exact details of the problem, as it's confidential. I have replaced it with Animals. typeOfAnimal below is a Fox, Cat, etc...
The IDefinition<T> object is an interface encompassing any definition of any Animal to be passed in.
The 'problem' i'm facing isn't exactly a blocking issue, this works, but it's using a standard I wouldn't be all too comfortable using..
It involves creating an instance of DefinitionOfFox, using this as an instance of the class to call a method on the class, and then passing this instance into that method as a param because it's needed further in that method. As expected, this works fine (passing in DefinitionOfFox as a type IDefinition<T>), but I want to refactor it so I'm not passing in the DefinitionOfFox object to the DefinitionOfFox class... and instead the DefinitionOfFox class creates the instance itself.
CURRENT STATE
public class Fox : Animal {
public void Init()
{
DefinitionOfFox definition = new DefinitionOfFox();
definition.Method1<Fox>(this, definition);
}
}
public class DefinitionOfFox : IDefinition<Fox>
{
public void Method1<T>(T typeOfAnimal, IDefinition<T> definition)
{
OtherService otherService = new OtherService();
otherService.Method2<T>(typeOfAnimal, definition);
}
}
All works fine in the current state, but it doesn't sit right with me passing the class instance in as a param to it's own class.
IDEAL STATE
public void Init()
{
DefinitionOfFox definition = new DefinitionOfFox();
definition.Method1<Fox>(this);
}
public class DefinitionOfFox : IDefinition<Fox>
{
public void Method1<T>(T typeOfAnimal)
{
DefinitionOfFox definition = new DefinitionOfFox();
OtherService otherService = new OtherService();
otherService.Method2<T>(typeOfAnimal, definition);
}
}
OtherService class and Method2
NB This method must be called from the DefinitionOfFox class, not from the Fox class.
public class OtherService
{
public void Method2<T>(T typeOfFox, IDefinition<T> definition)
{
}
}
I get a compiler error for definition when trying to pass this into the OtherService.Method2() method. It complains that it can't convert DefinitionOFox to IDefinition<T>.
How come this works in the current state, but not in the Ideal state? And is there a way I can have my Ideal state? It is the same object that is getting passed into the method, it's just created at a different time.
error says
Argument 2: Cannot convert from ....DefinitionOfFox to .... IDefinition
If this doesn't make sense, I can elaborate - no problem. Just let me know
Thanks for your time!
It seems that Method1 just should not be generic or have non-generic overload:
public class DefinitionOfFox : IDefinition<Fox>
{
public void Method1(Fox typeOfAnimal)
{
DefinitionOfFox definition = new DefinitionOfFox();
OtherService.Method2(typeOfAnimal, definition); // or OtherService.Method2(typeOfAnimal, this); based on goals
}
}
How come this works in the current state, but not in the Ideal state
Because in the ideal state the generic parameter T is closed with Fox so it "matches" for T and IDefinition<T>, for the "ideal" state imagine if your code was compiling then what should happen in the case of Method1<Rabbit>(...) invocation is DefinitionOfFox suitable for IDefinition<Rabbit> parameter?
If you still want your method to be generic and you want to create a new instance of IDefinition<T> inside then you will need to generic parameters with corresponding constraints:
public class DefinitionOfFox : IDefinition<Fox>
{
public void Method1<T, TDefinition>(T typeOfAnimal) where TDefinition : IDefinition<T>, new()
{
IDefinition<T> definition = new TDefinition();
OtherService otherService = new OtherService();
otherService.Method2<T>(typeOfAnimal, definition);
}
}
Related
EDIT: added follow up question from getting a solution suggested from another question
EDIT2: I just realised that my follow up question was not needed.
Is it possible to have an abstract base class with a type parameter of T have a constructor that takes a parameter of T and assigns it to a property of T? What i want to achieve is that all derived classes has a constructor that does this?
Something like:
public abstract class NotificationBase <T>
{
public string Text { get; set; }
public T Context { get; set; }
public NotificationBase(T context, string text)
{
Context = context;
Text = text;
}
}
public class NumberNotification : NotificationBase<int>{}
public class Program
{
public void Run()
{
var thing = new NumberNotification(10, "Hello!");
}
}
EDIT:
I got a link to another question that explained how to do this which is great. However i have some issues with that. And i dont mean its wrong, if that is the only way to do it then thats how it is. However its not the ideal situation for what im trying to do. I explain. This was the solution:
public class Base
{
public Base(Parameter p)
{
Init(p)
}
void Init(Parameter p)
{
// common initialisation code
}
}
public class Derived : Base
{
public Derived(Parameter p) : base(p)
{
}
}
..which works great. However it does create two small issues that id like to se if they can be addressed.
What i want is to force all classes that derives from the base to pass a T into the constructor so that its mandatory. With this solution, its possible to leave it out.
If all classes should do this then it feels redundant to create a constructor to propagate a mandatory parameter.
EDIT: I just realised that demanding a constructor that propagates the type parameter IS what im looking for. I makes sure that the T property gets a value and also allows for other things to happen in the constructor.
Yes, you can, you just need to propagate the constructor chain using the relevant type, and call the ancestor if needed:
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
: base(context, text)
{
}
}
Without constructor in child class, the instantiation you wrote can't compile because you don't offer a way for the compiler to know what to do.
You can also offer any other constructor needed.
Therefore now this compiles and works:
var thing = new NumberNotification(10, "Hello!");
Inheritance And Constructors (C# Corner)
base (C# Reference)
Define the parameterized constructor for NumberNotification class which should invoke the required constructor of NotificationBase using base
public class NumberNotification : NotificationBase<int>
{
public NumberNotification(int context, string text)
:base(context, text)
{
}
}
Now for NumberNotification object, context is type of int as here T is marked as int type which Yyou can check using below code:
var thing = new NumberNotification(10, "Hello!");
Console.WriteLine(thing.Context.GetType());
The above prints the output as System.Int32
Check the fiddle - https://dotnetfiddle.net/keufQO
I'm trying to make my code as re-usable as possible, and ran into a problem when trying to pass a constuctor argument to a class used as a type parameter.
What I currently have is this:
public sealed class SubmitForm : DerivedClass
{
}
public void TestMethod_Simulated()
{
var foo = GetObject<SubmitForm>();
SubmitData(foo);
}
private void SubmitData(SubmitForm form)
{
// Do work
}
public T GetObject<T>()
where T : class
{
// Work
}
This was working because there was no explicit constructor and parameter for SubmitForm. However I want to extend the functionality and require an explicit constructor expecting an argument.
After adding the constructor, I am looking to call "GetObject" with the type parameter "SubmitForm" INCLUDING an argument for its explicit constructor.
This is clearly not possible in any straightforward way, but I don't want to believe there is not way of getting this to work.
The following shows what I'm trying to achieve, which is to use the class as a type parameter while instantiating it in order to access the constructor I've created:
public sealed class SubmitForm : DerivedClass
{
public SubmitForm(EnumType typeVar)
{
_derivedVar = typeVar;
}
}
public void TestMethod_Simulated()
{
var foo = GetObject<new SubmitForm(EnumType.FormA)>();
SubmitData(foo);
}
private void SubmitData(SubmitForm form)
{
// Do work
}
public T GetObject<T>()
where T : class
{
// Work
}
I hope this makes sense. I can't seem to find a way to first instantiate the class AND then use it as a type parameter.
I hope this makes sense. I can't seem to find a way to first
instantiate the class AND then use it as a type parameter
Well, it is not possible to pass an instance of a class as generic type parameter.
A type parameter is just a placeholder for type of object. Compiler uses it to infer the type and substitute T with a real type. It has nothing to do with actual parameters.
If you want to use a specific instance of SubmitForm class in your function you could first create an instance:
var submitForm = new SubmitForm(EnumType.FormA);
And then change your function to accept an argument of type T:
public T GetObject<T>(T instance)
where T : class
{
// .. do something with instance
}
And now you can make a call to the new overload:
var someResult = GetObject(submitForm);
However from your code sample it's not clear why you need generic type parameters at all. It seems that you might just as well change the signature of GetObject function from T GetObject<T>() to SubmitForm GetObject(SubmitForm form)
We usually use type parameters when we have a generic function that needs to execute more or less same logics for different types and we don't want to duplicate the same code.
Currently I have something like this:
public abstract class Base {...}
public class Derived<T> : Base {...}
class Visitor {
public static void Visit<T>(Derived<T> d) {
...
}
}
My question is, given a Base reference that I know is a Derived instance, how can I apply that Visit function to that object, using the correct generic instantiation? I understand that the answer will probably involve a type-checked dynamic downcast, to make sure that the object isn't some other type derived from base, which is all fine. I assume the answer involves reflection, which is also fine, though I'd prefer if there was a way to do it without reflection.
It's also ok if the answer involves an abstract method on Base and Derived; I do have enough control of the classes to add that. But at the end of the day, I need to call a generic function, correctly instantiated with the T of the Derived type.
Sorry if this is an easy question; I come from a C++ background, where my instinct would be to use a CRTP or something else like that, which isn't possible in C#.
EDIT:
Here's an example of what I need to be able to do:
Base GetSomeDerivedInstance() { ...; return new Derived<...>(); }
var b = GetSomeDerivedInstance();
// This is the line that needs to work, though it doesn't necessarily
// need to have this exact call signature. The only requirement is that
// the instantiated generic is invoked correctly.
Visitor.Visit(b);
In my opinion, answers involving double-dispatch and More Classes are going to be superior than using reflection to do what inheritance should do for you.
Normally this means defining an 'accept' method on the visitable class, which simply calls the correct Visit method from the visitor.
class Base
{
public virtual void Accept(Visitor visitor)
{
visitor.Visit(this); // This calls the Base overload.
}
}
class Derived<T> : Base
{
public override void Accept(Visitor visitor)
{
visitor.Visit(this); // this calls the Derived<T> overload.
}
}
public class Visitor
{
public void Visit(Base #base)
{
...
}
public void Visit<T>(Derived<T> derived)
{
...
}
}
Then you can do what you mentioned in your question, with a small modification:
Base b = createDerived();
b.Accept(new Visitor());
If your visit method is a static class that you can't change for whatever reason, you could always wrap this into a dummy instance visitor class which calls the right static method.
(Edited for clarity)
The following will use a variable called "anyvalue" whose type is only known at run-time. Then we'll create an instance of your Derived class based on the type of anyvalue. Once we have that instance, we can use reflection to get the correct Visit method.
var anyvalue = 5; // This value could have come from anywhere.
...
var derivedType = typeof (Derived<>).MakeGenericType(anyvalue.GetType());
var dvalue = Activator.CreateInstance(derivedType);
var method = typeof(Visitor).GetMethod("Visit");
var genericMethod = method.MakeGenericMethod(new[] { anyvalue.GetType() });
genericMethod.Invoke(null, new [] { dvalue });
What is a little confusing is that this is a skeletal example and you do not use the original value for anything other than getting a run-time type. In the real world implementation, I would assume a constructor would use that value to set internal state in the Derived instance. That is not covered here because that is not part of the question that was asked.
UPDATE:
I think this will do what you want. Note that I created the itemarray so that we would have some run-time values. They have to be created somewhere. So whether they are passed in as object[] or provided some other way, they had to be constructed with a type specifier somewhere. Also, this assumes that Derived<> is the only derived class. Otherwise, this is not safe code.
var itemarray = new Base[] { new Derived<int>(), new Derived<string>() };
foreach (var baseObject in itemarray)
{
var derivedType = baseObject.GetType();
var visitMethod = typeof(Visitor)
.GetMethod("Visit")
.MakeGenericMethod(derivedType.GetGenericArguments());
visitMethod.Invoke(null, new[] { baseObject });
}
The Accept approach does seem a bit more manageable. My goal was to answer the question you asked without passing judgment on your approach. I have needed to use this approach several times. I wrote an entity framework about 9 years ago. I had a really hard time doing exactly what you are trying to do. I created base classes that were not generic so that I could share basic functionality regardless of the generic type. It proved challenging. I am not sure I would do it the same way now. I'd probably investigate a few patterns just as you are doing.
You should be able to do something like the following:
Base foo = new Derived<int>();
var method = typeof(Visitor).GetMethod("Visit", BindingFlags.Public | BindingFlags.Static);
method.MakeGenericMethod(foo.GetType().GenericTypeArguments.First()).Invoke(null, new[] {foo});
Perhaps you're meaning something like this?
public class Derived<T>
{
}
public abstract class Derivable<T>
{
public Derived<T> CreateDerived()
{
return new Derived<T>();
}
}
public class Foo : Derivable<Foo>
{
}
class Visitor
{
public static void Visit<T>(Derived<T> obj)
{
Console.Out.WriteLine("Called!");
}
}
void Main()
{
var obj = new Foo();
var derived = obj.CreateDerived();
Visitor.Visit(derived);
}
If the creation of the Derived<T> is T-specific, then you'd make the CreateDerived method abstract and implement it for each T. Or use an IDerivable<T> interface instead if you don't want it as your base class.
Its been a while but i need to convert some custom code into C# (i think it was called emeralds or something somebody else gave to me). there is a certain method that takes a class(any class without any object conversions). this is the code im trying to convert.
class management
Accessor current_class
Accessor class_Stack
def call(next_class) #method, called global, takes a "class" instead
#of a variable, kinda odd
stack.push(current_class) #stack handling
current_class = next_class.new #makes a new instance of specified next_class
end
end
next_class seems to be any class related to a base class and assigns a new instance of them to a variable called currentClass. there are other "methods" that do something similar. I've tried setting the parameter type to "object", but loses all the the "next_class" attributes that are needed. this is my attempt at it
public class management {
public Stack stack;
public Someclass currentClass;
public void Call(object nextClass) {
stack.push(currentClass); // stack handling
currentClass = new nextClass(); // conversion exception, otherwise loss of type
}
}
IS this even possible in C#
another thing this language seems to able to keep attributes(methods too) from Child classes when you cast them as a base class. e.g cast green bikes as just bikes but it will still be green
can somebody point me in the right direction here? or do i need to rewrite it and change the way it does things?
What you want is Generics and I think also, based on the fact that you call a method, Interfaces.
So your Interface will define "new" and the Class will inherit from the interface.
You can then pass the class as a generic and call the Interface method of "new" on it.
So;
public interface IMyInterface
{
void newMethod();
}
public class MyClass1 : IMyInterface
{
public void newMethod()
{
//Do what the method says it will do.
}
}
public class Class1
{
public Class1()
{
MyClass1 classToSend = new MyClass1();
test<IMyInterface>(classToSend);
}
public void test<T>(T MyClass) where T : IMyInterface
{
MyClass.newMethod();
}
}
EDIT
And check out "dynamic" in C# 4.0. I say this because if you don't know what the method is until runtime you can define it as dynamic and you are basically telling the compiler that "trust me the method will be there".
This is in case you can't use generics because the methods you call will be different for each class.
In a non-static method I could use this.GetType() and it would return the Type. How can I get the same Type in a static method? Of course, I can't just write typeof(ThisTypeName) because ThisTypeName is known only in runtime. Thanks!
If you're looking for a 1 liner that is equivalent to this.GetType() for static methods, try the following.
Type t = MethodBase.GetCurrentMethod().DeclaringType
Although this is likely much more expensive than just using typeof(TheTypeName).
There's something that the other answers haven't quite clarified, and which is relevant to your idea of the type only being available at execution time.
If you use a derived type to execute a static member, the real type name is omitted in the binary. So for example, compile this code:
UnicodeEncoding.GetEncoding(0);
Now use ildasm on it... you'll see that the call is emitted like this:
IL_0002: call class [mscorlib]System.Text.Encoding
[mscorlib]System.Text.Encoding::GetEncoding(int32)
The compiler has resolved the call to Encoding.GetEncoding - there's no trace of UnicodeEncoding left. That makes your idea of "the current type" nonsensical, I'm afraid.
Another solution is to use a selfreferecing type
//My base class
//I add a type to my base class use that in the
//static method to check the type of the caller.
public class Parent<TSelfReferenceType>
{
public static Type GetType()
{
return typeof(TSelfReferenceType);
}
}
Then in the class that inherits it, I make a self referencing type:
public class Child: Parent<Child>
{
}
Now the call type typeof(TSelfReferenceType) inside Parent will get and return the Type of the caller without the need of an instance.
Child.GetType();
You can't use this in a static method, so that's not possible directly. However, if you need the type of some object, just call GetType on it and make the this instance a parameter that you have to pass, e.g.:
public class Car {
public static void Drive(Car c) {
Console.WriteLine("Driving a {0}", c.GetType());
}
}
This seems like a poor design, though. Are you sure that you really need to get the type of the instance itself inside of its own static method? That seems a little bizarre. Why not just use an instance method?
public class Car {
public void Drive() { // Remove parameter; doesn't need to be static.
Console.WriteLine("Driving a {0}", this.GetType());
}
}
I don't understand why you cannot use typeof(ThisTypeName). If this is a non-generic type, then this should work:
class Foo {
static void Method1 () {
Type t = typeof (Foo); // Can just hard code this
}
}
If it's a generic type, then:
class Foo<T> {
static void Method1 () {
Type t = typeof (Foo<T>);
}
}
Am I missing something obvious here?
When your member is static, you will always know what type it is part of at runtime. In this case:
class A
{
public static int GetInt(){}
}
class B : A {}
You cannot call (edit: apparently, you can, see comment below, but you would still be calling into A):
B.GetInt();
because the member is static, it does not play part in inheritance scenarios. Ergo, you always know that the type is A.
For my purposes, I like #T-moty's idea. Even though I have used "self-referencing type" information for years, referencing the base class is harder to do later.
For example (using #Rob Leclerc example from above):
public class ChildA: Parent<ChildA>
{
}
public class ChildB: Parent<ChildB>
{
}
Working with this pattern can be challenging, for example; how do you return the base class from a function call?
public Parent<???> GetParent() {}
Or when type casting?
var c = (Parent<???>) GetSomeParent();
So, I try to avoid it when I can, and use it when I must. If you must, I would suggest that you follow this pattern:
class BaseClass
{
// All non-derived class methods goes here...
// For example:
public int Id { get; private set; }
public string Name { get; private set; }
public void Run() {}
}
class BaseClass<TSelfReferenceType> : BaseClass
{
// All derived class methods goes here...
// For example:
public TSelfReferenceType Foo() {}
public void Bar(TSelfRefenceType obj) {}
}
Now you can (more) easily work with the BaseClass. However, there are times, like my current situation, where exposing the derived class, from within the base class, isn't needed and using #M-moty's suggestion just might be the right approach.
However, using #M-moty's code only works as long as the base class doesn't contain any instance constructors in the call stack. Unfortunately my base classes do use instance constructors.
Therefore, here's my extension method that take into account base class 'instance' constructors:
public static class TypeExtensions
{
public static Type GetDrivedType(this Type type, int maxSearchDepth = 10)
{
if (maxSearchDepth < 0)
throw new ArgumentOutOfRangeException(nameof(maxSearchDepth), "Must be greater than 0.");
const int skipFrames = 2; // Skip the call to self, skip the call to the static Ctor.
var stack = new StackTrace();
var maxCount = Math.Min(maxSearchDepth + skipFrames + 1, stack.FrameCount);
var frame = skipFrames;
// Skip all the base class 'instance' ctor calls.
//
while (frame < maxCount)
{
var method = stack.GetFrame(frame).GetMethod();
var declaringType = method.DeclaringType;
if (type.IsAssignableFrom(declaringType))
return declaringType;
frame++;
}
return null;
}
}
EDIT
This methods will works only when you deploy PDB files with the executable/library, as markmnl pointed out to me.
Otherwise will be a huge issue to be detected: works well in developement, but maybe not in production.
Utility method, simply call the method when you need, from every place of your code:
public static Type GetType()
{
var stack = new System.Diagnostics.StackTrace();
if (stack.FrameCount < 2)
return null;
return (stack.GetFrame(1).GetMethod() as System.Reflection.MethodInfo).DeclaringType;
}