Is there a way to assign generic through instantiation? - c#

Is there a way to assign T through instantiation as in the following "hypothetical" example:
MyObject DummyObject = new MyObject();
DummyObject.MyNestedObject = new MySecondObject<string>()
public class MyObject //**Normally is specified as MyObject<T>**
{
public MySecondObject<T> MyNestedObject { get; set; }
}
I want to define T on instantiation of MySecondObject. I dont want to define it in MyObject.

No, you have to declare T in your class. Otherwise T won't exist in that context.
public class MyObject<T>
Another way would be to create an interface, implement it in your MySecondObject generic class.Then make the property type to interface instead of MySecondObject<T>
interface IMyInterface
{
}
class MySecondObject<T> : IMyInterface
{
}
public class MyObject
{
public IMyInterface MyNestedObject { get; set; }
}

Related

How to cast into generic base class

I have few classes which inherits from a generic class like FooBasePolicy<TFooTarget>. And I want to cast my derived classes by their base class (not sure if its right way to say it). My classes are:
public class FooTarget{}
public class GTeamTarget : FooTarget{}
public class MTeamTarget : FooTarget{}
public class FooBasePolicy{}
public class FooBasePolicy<TFooTarget> : FooBasePolicy where TFooTarget : FooTarget
{
public virtual TFooTarget SomeFooTarget { get;set; }
}
public class GTeamPolicy : FooBasePolicy<GTeamTarget>
{
public GTeamPolicy()
{
SomeFooTarget = new GTeamTarget();
}
}
public class MTeamPolicy : FooBasePolicy<MTeamTarget>
{
public GTeamPolicy()
{
SomeFooTarget = new MTeamTarget();
}
}
And then I tried to use these this way,
problem is I don't know upfront which TeamTarget it is. It can be G or M.
FooBasePolicy<FooTarget> policy = null;
if (something.Equals("GTEAM"))
{
//This gives me an implicit conversion error. It can't cast.
policy = FromBinary(type, funnelData.Data) as FooBasePolicy<FooTarget>;
}
else if (something.Equals("MTEAM"))
{
policy = FromBinary(type, funnelData.Data) as FooBasePolicy<FooTarget>;
}
FromBinary actually returns a deserialized object.
But it perfectly can cast into FooBasePolicy. But then I miss SomeFooTarget property.
Any idea? Please help.
As the others said, just define an interface:
public interface IFooBasePolicy<out TFooTarget> {
TFooTarget SomeFooTarget { get; }
}
The base class FooBasePolicy now looks like:
public class FooBasePolicy<TFooTarget> : IFooBasePolicy<TFooTarget>
where TFooTarget : FooTarget {
public virtual TFooTarget SomeFooTarget { get; set; }
}
Later you can use the following cast:
policy = ((IFooBasePolicy<FooTarget>)FromBinary(something));
Short explanation:
FooBasePolicy<FooTarget> is not a base class of FooBasePolicy<GTeamTarget>
this can be resolved with covariance: GTeamTarget is a subtype of FooTarget, therefore FooBasePolicy<GTeamTarget> is a subtype of FooBasePolicy<FooTarget>
but covariance is only allowed on interfaces in C#
so you need an interface with a coveriant type declaration

How to downcast this to the base class?

I have this class hierarchy:
public abstract class AClass : SomeFrameworkClass {
[WorkOnThisProperty(With.Some.Context)]
private MyObject MyProperty { get; set; }
public override void OnSomethingHappened() {
ExternalFramework.WorkOn(this);
}
}
public class BClass : AClass {
// ... Snip ...
}
ExternalFramework is operating on this: an instance of BClass but i need it to operate on this as an instance of AClass because ExternalFramework only works on the type of the object passed in and does not go up the inheritance hierarchy. How can i downcast this into AClass so ExternalFramework can actually detect MyProperty?
I've tried casting this to object and then to AClass, and casting it directly to AClass but as the cast is unnecessary it doesn't seem to run. What can i do about this?
EDIT: ExternalFramework is Cheeseknife. I am trying to inject a couple views into a base fragment class that has all the reusable logic while child fragment classes implement some specific behaviour tuning.
The problem is that all private members of a class can only be accessed inside of the same class.
With this code:
class A { private string Property { get; set; } }
class B : A { public string Proxy => Property; }
We'll get compilation error because class B cannot access private property from class A, but if change keyword to protected :
class A { protected string Property { get; set; } }
It should work.

List of generic objects with default constructor

I just have this simple generic class, which should take T and create one property. If I try to get this property and it does not exists, it should create new instance of this T type and return it. That is why I need to set new() constraint on T.
public class ExternalRepository<T> where T : class, IRepositoryable, new()
{
public IRepositoryable Value
{
get
{
if (RequestCacheManager.GetAt<T>(typeof(T).Name) == null)
RequestCacheManager.SetAt<T>(typeof(T).Name, new T());
return RequestCacheManager.GetAt<T>(typeof(T).Name);
}
}
}
And now I need to create a list of these. But it looks like it is imposible, because of the new() constraint. I'm need something like this:
public static List<ExternalRepository<T>> ExternalRepositories { get; set; } where T : class, IRepositoryable, new()
But this is not valid. Could you please help me solve this?
Thank you.
You want to put, let's say, ExternalRepository<Person> and ExternalRepository<Order> together in a list, correct?
Sadly, this can't be done explicitly. You'll have to use an interface or base class.
public interface IExternalRepository
{
// declaration of common properties and methods
}
public class ExternalRepository<T> : IExternalRepository
where T : class, IRepositoryable, new()
{
// implementation of common properties and methods
// own properties and methods
}
public static List<IExternalRepository> ExternalRepositories { get; set; }
or
public class ExternalRepository
{
// shared properties and methods
}
public class ExternalRepository<T> : ExternalRepository
where T : class, IRepositoryable, new()
{
// own properties and methods
}
public static List<ExternalRepository> ExternalRepositories { get; set; }
See also my reply to this question.

Get an interface property value in a generic class

I have this interface
public interface IMyInterface
{
IEnumerable<MyParamInfo> Params { get; }
}
where
MyParamInfo is
public class MyParamInfo
{
public MyParamInfo (string name)
{
Name= name;
}
public string Name { get; private set; }
}
also
this class
public class MyClass:IMyInterface
{
//properties
....
public IEnumerable<MyParamInfo> Params
{
get
{
return new List<MyParamInfo> { new MyParamInfo("Param1")};
}
}
}
and this Form
public partial class MyForm<T> : Form where T:Class,IMyInterface
{
...
}
with this code
MyForm<MyClass> frm = new MyForm<MyClass>();
How can I access to Params Property of MyClass in frm object?
If you also require that the T type parameter of MyForm have a parameterless constructor, you can instantiate an instance of T and then use the interface property at will.
On the definition of MyForm, add the new() generic constraint
public partial class MyForm<T> : Form where T : Class, IMyInterface, new()
Then in some method of MyForm<T>, you can use:
(new T()).Params;
You can read about all the constraints on type parameters in C# here.
It seems like what you really want is interfaces that could specify static methods (so-called static interfaces). Such a construct does not exist in C#.

C#: Generic Inherited Factories

I have a base class that takes a single generic argument. I then have several classes that inherit from this base class. Is there a simple way for the child classes to inherent a factory from the base class?
Example
class BaseClass<T>
{
T Value {get; set;}
string Name {get; set;}
public static BaseClass<T> Factory(T Value)
{
return new BaseClass<T>(Value);
}
}
class ChildClass : BaseClass<int>
{
public void Test()
{
// I want this below to work
// but Factory() returns a BaseClass
ChildClass bs = ChildClass.Factory(10);
}
}
I've noted in the code what I want to work. I can think of one way to overcome this, by adding an implicit operator to either BaseClass or SubClass that converts from BaseClass to ChildClass.
I can also just explicitly add the Factory to ChildClass but that defeats the point of inheritance.
Is there a better, more standardized way of doing this?
I would do something like this:
class BaseClass<T, K> where K : BaseClass<T, K>, new()
{
T Value { get; set; }
string Name { get; set; }
public static K Factory(T value)
{
return new K { Value = value };
}
}
class ChildClass : BaseClass<int, ChildClass>
{
public void Test()
{
ChildClass cs = Factory(10);
}
}
It's a bit hard to answer your question since you have described what you are trying to do, but not why. Hence I got to try to guess what you want.
I would not put the factory method in the same class as in the other answer or your question. How would you handle inheritance for once? It works for the two levels that you have. But what if you want to extend ChildClass?
Instead I would create a generic factory used for the object creation. Implement it has a singleton wrapped around a factory interface to be able to easy extend it or swap the implementation.
class MyFactory
{
private static IMyFactory _instance;
public static void Assign(IMyFactory factory) { _instance = factory; }
public static T Create<T>() { return _instance.Create<T>(); }
}
interface IMyFactory
{
T Create<T>();
}
class MyFactoryImp : IMyFactory
{
//do whatever needed in here
public T Create<T>(){ return new T(); }
}
class BaseClass<T>
{
T Value {get; set;}
string Name {get; set;}
}
class ChildClass : BaseClass<int>
{
public void Test()
{
ChildClass bs = MyFactory.Create<ChildClass>(10);
}
}
// start with this, you can easily switch implementation
MyFactory.Assign(new MyFactoryImp());
The other obvious answer would be to start using a Inversion Of Control container, for example autofac.

Categories