Dynamic cast behavior in loop - c#

I'm trying to accomplish some hacking & slashing and was wondering how to approach the following.
There are 2 interfaces defined:
public interface IBase
{
string Name { get; }
void Run();
}
public interface ISecondBase<T> : IEntityTask
{
Thing<T> Thing { get; }
}
Somewhere else I have a list of IBase.
This list is filled ISecondBase. I would like to be able to loop through the list of Base, but using some reflection tricks and hacks als be able to call Thing on the items. I know they're there, the compiler doesn't.
So I'd have to cast it to its concrete type at runtime, but this cast has to be dynamic, based on reflected information in the loop... So all type information is dynamic... I'm starting to think in circles :)
Since I know on beforehand that everything inside it is always of the SecondBase type, I decided to use the dynamic keyword and just let it resolve at runtime. This seems to me like an easy way out. Is there some best practice for these cases? Should I redesign, without loss of generality, and how?
foreach(var x in y)
{
dynamic melp = x;
melp.Thingy;
}
Where to start?
Edit: Perhaps some more code to make the example less contrived.
I have the base classes as mentioned. In real life they look like this:
public interface IEntityTask
{
string Name { get; }
void Run();
}
public interface IEntityTask<T> : IEntityTask
{
Task<T> Task { get; }
}
//Then there are classes that implement these:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
public T Entity { get; private set; }
public Func<T, Guid> EntityMethod { get; private set; }
public Task<Guid> Task { get; private set; }
public void Run()
{
Task = Task<Guid>.Run(() => entityAccess.CreateEntity<T>(Entity, EntityMethod));
}
}
public class ReadEntityTask<T> : IEntityTask<T>
{
public Guid EntityId { get; private set; }
public Func<Guid, T> EntityMethod { get; private set; }
public Task<T> Task { get; private set; }
public void Run()
{
Task = Task<T>.Run(() => entityAccess.ReadEntity<T>(EntityId, EntityMethod));
}
}
//Furthermore there is a class called EntityTaskManager, which holds a list of these things and runs, awaits & collects the results on them.
public class EntityTaskManager
{
public List<IEntityTask> EntityTasks { get; set; } // I want tasks of Guid and bool in here!!!!
public Dictionary<string, object> EntityTaskResults { get; set; }
}
In a calling class I construct a new EntityTask and add it to the list. And then call RunTasks on the manager.

I'd modify IEntityTask like this:
public interface IEntityTask
{
string Name { get; }
void Run();
object Result { get; }
}
If EntityTaskManager is the only place, where you work with IEntityTask type, the implementation of Result would be explicit:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
/* The rest of code here */
object IEntityTask.Result
{
get { return Task.Result; }
}
}
Then fetching task results should be trivial:
var results = entityTasksManager
.EntityTasks
.Select(t => t.Result);

Related

c#: Interface needs to have a property off implementing class type

I need to have something like this. So a class that implements this Interface needs to get a property with the same type as the class.
Is this even possible, ifso how? I'm using .net 6.
public interface IProperty
{
public typeof(this) parameter { get; } // doesn't work, can't use typeof()
}
public class clsResourceProperty : IProperty
{
public clsResourceProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public clsInterfaceProperty parameter { get; }
}
I know how to use generic interfaces, and with the second example it works, but clsResourcePropertyGeneric: IPropertyGeneric looks strange. And doens't work for the application i need.
public interface IPropertyGeneric<T>
{
public T parameter { get; }
}
public class clsResourcePropertyGeneric: IPropertyGeneric<clsResourcePropertyGeneric>
{
public clsResourcePropertyGeneric parameter { get; }
}
public class clsInterfacePropertyGeneric: IPropertyGeneric<clsInterfacePropertyGeneric>
{
public clsInterfacePropertyGeneric parameter { get; }
}
In the application i need, i need to have a class containing a list of this interface. So something like this:
public class clsState
{
public List<IProperty> data {get; private set;}
public clsState(List<IProperty> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
But this doesn't work with the generic interface. I need to make a class containing a list of this interface, where i define the generic type T. But this list can't contain ALL classes which implement this interface
public class clsState<T>
// need to add T here to use it in the list, but the list needs to contain ALL implementing class types, not only 1
{
public List<IProperty<T>> data {get; private set;}
public clsState(List<IProperty<T>> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
I found this link, but this is from 7 years ago, so maybe there is some evolution in this aspect?
You can use the interface as your property type, as in:
public interface IProperty
{
public IProperty parameter { get; }
}
public class clsResourceProperty : IProperty
{
public IProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public IProperty parameter { get; }
}
As for having a collection of the interfaces, it is possible to collect all of the classes for a particular type or interface. This is from a piece of code in one of my libraries. It doesn't do exactly what you're after, but it might be a step towards your final solution.
private static Type[] strategyTypes;
private readonly static Type[] obsoleteTypes = new Type[]
{
};
static StrategyRepository()
{
strategyTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType == typeof(Strategy))
.Except(obsoleteTypes)
.ToArray();
}
This question might be a more direct answer to that part of your question: Getting all types that implement an interface

Covariance, generic, UserControl

I have created a user control that contains an ObservableCollection<Something>. I learned that I cannot cast say ObservableCollection<Tiger> to ObservableCollection<Animal>. The solution I found was to add a helper class that handles all low level collection manipulation. My suspicion is that there is a more elegant solution and if so, maybe someone can point me into that direction.
See the code below that captures the problem and my solution. Zoo corresponds to the WPF UserControl. (Actually a zoo for one type od animal.) Ideally I would define it as Zoo<T> i.e. as a generic type but that would prevent me from using XAML. I need to define Animals as object in order assign to it.
class Program
{
public static void Main(string[] args)
{
Zoo zoo = new Zoo();
List<Tiger> tigers = new List<Tiger>() { new Tiger() };
zoo.Animals = tigers;
zoo.Helper = new TigerHelper(tigers);
Console.WriteLine(zoo.GetCount());
Console.ReadLine();
}
}
public class Animal { }
public class Tiger : Animal { }
public interface Helper { int GetCount(); }
public class TigerHelper : Helper
{
private List<Tiger> tigers;
public TigerHelper(List<Tiger> tigers) { this.tigers = tigers; }
public int GetCount() { return tigers.Count; }
}
public class Zoo
{
public object Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Helper.GetCount(); }
}
Rather than go all the way down to object, you can use IList. This gives you access to most of the features of the list, but without the generics. For example, you can still access the Count property:
public class Zoo
{
public IList Animals { get; set; }
public Helper Helper { get; set; }
public int GetCount() { return Animals.Count; }
}

Can't see properties from interface

I'm having some interface woes!
Here's the code:
I expected to be able to access the properties Added and ID through my test template, but intellisense says No!
Am I misusing an interface? Have I made a silly error?
Any advice appreciated - this is driving me nuts.
namespace blah.blah.blah
{
public interface ITrackedItem
{
DateTime Added { get; set; }
int ID { get; set; }
}
public class TestTemplate<ITrackedItem>
where ITrackedItem : new()
{
public SortedSet<ITrackedItem> Set { get; set; }
public void Test()
{
Set = new SortedSet<ITrackedItem>();
foreach (var item in Set)
{
// cannot access any properties here
// var ID = item.ID; <=============|
}
}
}
}
This is the problem:
public class TestTemplate<ITrackedItem>
You've declared a type parameter called ITrackedItem, which is entirely different to the ITrackedItem interface. It's not clear that your type needs to be generic at all - can you not just use
public class TestTemplate
? If you want it to be generic in a type which must implement ITrackedItem, you should use something like:
public class TestTemplate<T>
where T : ITrackedItem, new()
{
public SortedSet<T> Set { get; set; }
public void Test()
{
Set = new SortedSet<T>();
foreach (var item in Set)
{
// now you can access any properties here
//
}
}
}

Register abstract managed classes with generic managing class and preserve one-to-many relationship

I have a couple abstract classes, and would like to make sure that the "Manager" is always registered with the "Managed" class such that they retain a two-way knowledge of the one-to-many relationship. That is, the Manager knows all of the Managed classes it has, and the Managed class knows who its Manager is (if it is registered with one). Further, I'd like the managed class to be able to call the specialization of its concrete manager without having to do a special cast. Is that possible?
I'd like something like this, but run into compilation issues:
class Program
{
static void Main(string[] args)
{
ConcreteManager manager = new ConcreteManager();
ConcreteManaged managed = new ConcreteManaged() { Name = "Test" };
manager.Add(managed);
managed.Process();
}
}
public abstract class BaseManager<ManagedType>
where ManagedType : BaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = this; // Cannot implicitly convert type 'BaseManager<ManagedType>' to 'BaseManager<BaseManaged>' (I've tried casting to no avail)
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<BaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh Called"); }
}
public abstract class BaseManaged
{
public string Name { get; set; }
public BaseManager<BaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
Manager.Refresh();
}
}
If I change the non Program classes around a bit, as follows, I can get it to compile, but there are runtime errors (Unable to cast object of type 'TestAbstractGenerics.ConcreteManager' to type 'TestAbstractGenerics.IBaseManager`1[TestAbstractGenerics.IBaseManaged]'.):
public interface IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
void Add(ManagedType service);
}
public abstract class BaseManager<ManagedType> : IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = (IBaseManager<IBaseManaged>)this;
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<BaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public interface IBaseManaged
{
string Name { get; set; }
IBaseManager<IBaseManaged> Manager { get; set; }
}
public abstract class BaseManaged : IBaseManaged
{
public string Name { get; set; }
public IBaseManager<IBaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
((ConcreteManager)Manager).Refresh();
}
}
If I change the IBaseManager<IBaseManaged> to dynamic I can remove the cast from Process() and everything works as expected, but dynamic doesn't work with intellisense, and I would like to be able to enforce the type checking (so an implementer can't accidentally set Manager to a string, for example). So what's the best practice here? Is there a good pattern to follow that allows me to preserve the one-to-many relationship?
And yes, in the above I'd have to add some logic to make sure that when BaseManaged.Manager is set that it unregisters from its current Manager, if any. I avoided that here for sake of simplicity.
Edit: this works, but still requires casting to the ConcreteManager prior to calling its non-interface methods:
class Program
{
static void Main(string[] args)
{
var manager = new ConcreteManager();
var managed = new ConcreteManaged() { Name = "Test"};
manager.Add(managed);
managed.Process();
}
}
public interface IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
void Add(ManagedType managed);
}
public abstract class BaseManager<ManagedType> : IBaseManager<ManagedType>
where ManagedType : IBaseManaged
{
protected Dictionary<string, ManagedType> registered = new Dictionary<string, ManagedType>();
public void Add(ManagedType managed)
{
managed.Manager = (IBaseManager<IBaseManaged>)this;
registered.Add(managed.Name, managed);
}
// Other common management tasks
}
public class ConcreteManager : BaseManager<IBaseManaged>
{
//specialization stuff, e.g.
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public interface IBaseManaged
{
string Name { get; set; }
IBaseManager<IBaseManaged> Manager { get; set; }
}
public abstract class BaseManaged : IBaseManaged
{
public string Name { get; set; }
public IBaseManager<IBaseManaged> Manager { get; set; }
}
public class ConcreteManaged : BaseManaged
{
//specialization stuff, e.g.
public void Process()
{
((ConcreteManager)Manager).Refresh();
}
}
I'm pretty sure the kind of cyclic relationship you want is not possible to implement perfectly type safe and without casts, because the compiler would end up getting into infinite cycles if you wanted IBaseManaged also to be generic (ie, IBaseManaged<T> where T : IBaseManager<?>), is clearly not possible to specify the constraint you need in place of ?.
You can however, create a third interface/class which can fully express this kind of circular constraint, which might provide an alternative solution.
interface IManagerAdapter<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager>
IMO, if your ConcreteManaged class is going to know directly about ConcreteManager by virtue of the type cast anyway, these classes don't really provide much more than a pattern to follow for concrete types, the abstraction is kind of broken. If you need this tight coupling between the specific concrete manager and managed types anyway, I would probably make it explicity by adding the specific type in place of Managed in each class, and do away with the BaseManaged class, which doesn't help very much other than providing the Name, which is simple enough to re-implement in concrete instances.
public interface IBaseManaged<T> {
string Name { get; set; }
T Manager { get; set; }
}
public class ConcreteManaged : IBaseManaged<ConcreteManager> {
public string Name { get; set; }
public ConcreteManager Manager { get; set; }
public void Process ()
{
Manager.Refresh ();
}
}
For anything in the base types which might be more complex to implement than Name, I would opt for a Mixin like approach, where you implement that additional functionality in a separate class, and just provide a property in the interface to retreive the Mixin. For example, if all the Manager classes need to account for registering all of the Managed (as with your Add()), you obviously don't want to duplicate that functionality in each Manager - but you could simplify the approach by implementing some ManagedRegister<T> type, say (can be whatever you like), and giving the IBaseManager type a Registered field to retreive an instance.
public interface IBaseManager<T> {
ManagedRegister<T> Registered { get; set; }
}
public class ConcreteManager : IBaseManager<ConcreteManaged> {
public ManagedRegister<ConcreteManaged> Registered { get; set; }
public void Refresh () { Console.WriteLine("Refresh() called"); }
}
You still get a strongly typed Managed instances from the Register inside the Manager here.
The change from your calling code is that instead of manager.Add(managed), it becomes manager.Registered.Add(managed), and you also need to create an instance of ManagedRegister<ConcreteManaged> to pass to the ConcreteManager.. Perhaps a bit messy, and I would suggest abstracting that away into a factory, which will prevent simple mistakes like forgetting to add managed instances to the manager. We can use that circular constraint from above to implement it in a type safe way. (And if it's possible to assume every Managed/Manager has a parameterless constructor, a single implementation will work by using new() constraints. Otherwise you'll want an abstract factory and implement for each concrete type).
interface IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager>
{
TManager Manager { get; }
TManaged Create (string name);
}
public abstract class ManagerFactory<TManager, TManaged>
: IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>, new()
where TManaged : IBaseManaged<TManager>, new()
{
TManager manager = new TManager ();
public ManagerFactory () {
manager.Registered = new ManagedRegister<TManaged> ();
}
public TManager Manager { get { return manager; } }
public TManaged Create (string name)
{
TManaged result = new TManaged ();
result.Name = name;
manager.Registered.Add (result.Name, result);
result.Manager = manager;
return result;
}
}
public class ConcreteFactory
: ManagedFactory<ConcreteManager, ConcreteManaged> { }
Back to Main, the usage is slightly simplified here.
ConcreteFactory f = new ConcreteFactory ();
ConcreteManaged managed = f.CreateManaged ("Test");
managed.Process ();
EDIT:
Here's abstracting all of the common functionality into so called "Base classes". The key difference here is that the Base classes composed into the concrete class rather than inherited, by means of the Base property, which acts very much like the base. prefix you'd use to call base members usually.
public class BaseManager<T> {
public Dictionary<string, T> Registered { get; set; }
}
public interface IBaseManager<T> {
BaseManager<T> Base { get; set; }
}
public class ConcreteManager
: IBaseManager<ConcreteManaged> {
public BaseManager<ConcreteManaged> Base { get; set; }
public void Refresh() { Console.WriteLine("Refresh() called"); }
}
public class BaseManaged<T> {
public string Name { get; set; }
public T Manager { get; set; }
}
public interface IBaseManaged<T> {
BaseManaged<T> Base { get; set; }
}
public class ConcreteManaged
: IBaseManaged<ConcreteManager> {
public BaseManaged<ConcreteManager> Base { get; set; }
internal ConcreteManaged () { }
public void Process () {
Base.Manager.Refresh ();
}
}
interface IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>
where TManaged : IBaseManaged<TManager> {
TManager Manager { get; }
TManaged Create (string name);
}
public abstract class BaseManagerFactory<TManager, TManaged>
: IManagerFactory<TManager, TManaged>
where TManager : IBaseManager<TManaged>, new()
where TManaged : IBaseManaged<TManager>, new() {
TManager manager = new TManager();
public BaseManagerFactory() {
manager.Base = new BaseManager<TManaged>();
manager.Base.Registered = new Dictionary<string, TManaged>();
}
public TManager Manager { get { return manager; } }
public TManaged Create (string name) {
TManaged result = new TManaged();
result.Base = new BaseManaged<TManager>();
result.Base.Name = name;
manager.Base.Registered.Add (name, result);
result.Base.Manager = manager;
return result;
}
}

Cascading extension methods for multiple interfaces?

I have multiple interfaces that my objects can implement. I am wondering if there is a way to "cascade" one extension method into another while using the same method name. I may be looking at this all wrong, but here is an example:
public interface IBaseDto
{
int Id {get;set;}
string CreatedByFullName {get;set;}
}
public interface IDocumentDto
{
List<ContactDto> Subscriptions {get;set;}
}
public class ContactDto: IBaseDto
{
public int Id {get;set;}
public string CreatedByFullName {get;set;}
public string FirstName {get; set}
public string LastName {get;set;}
}
public class MeetingDto: IDocumentDto
{
public int Id {get;set;}
public string CreatedByFullName {get;set;}
public List<ContactDto> Subscriptions {get;set;}
}
So, let's say I want to convert the DTOs into entities using an extension method. An example would be MeetingDto.ToEntity();
I am trying to think if I can write part of the extension method for an IBaseDto, another for the IDocumentDto and then for each concrete implementations for just their own properties. When I call MeetingDto.ToEntity() it would first hit the meeting extension method and call the IDocumentDto version, fill in what it needed, and then the IDocumentDto would call the IBaseDto. I hope this makes sense.
UPDATE:
I came up with this and it works pretty well:
public static TBaseDto ToEntity<TBridgeDto>(this TBaseDto dto) where TBaseDto: IBaseDto
{
...
return dto;
}
public static TDocumentDto ToEntity<TDocumentDto>(this TDocumentDto dto, IDocumentDto currentDto) where TDocumentDto : IDocumentDto
{
...
return dto.ToEntity();
}
public static MeetingDto ToEntity(this RfiDto dto)
{
...
return dto.ToEntity(dto)
}
Like this?
public static class Helper
{
public static void ToEntity(this MeetingDto source)
{
Console.WriteLine ("MeetingDto.ToEntity");
//Do Stuff
(source as IDocumentDto).ToEntity();
}
public static void ToEntity(this ContactDto source)
{
Console.WriteLine ("ContactDto.ToEntity");
//Do Stuff
(source as IBaseDto).ToEntity();
}
public static void ToEntity(this IDocumentDto source)
{
Console.WriteLine ("IDocumentDto.ToEntity");
//Do Stuff
foreach (var element in source.Subscriptions)
{
element.ToEntity();
}
}
public static void ToEntity(this IBaseDto source)
{
Console.WriteLine ("IBaseDto.ToEntity");
//Do Stuff
}
}
Yes you can..... just cast to the interface you want...
eg
interface I1
{
int Id { get; set; }
}
public interface I2
{
string Name { get; set; }
}
public class Blah : I1, I2
{
public int Id { get; set; }
public string Name { get; set; }
}
static class ExtendIt
{
public static void ToEntity(this I1 x)
{
x.Id = 1;
}
public static void ToEntity(this I2 x)
{
x.Name = "hello";
}
public static void ToEntity(this Blah x)
{
(x as I1).ToEntity();
(x as I2).ToEntity();
}
}
Extension methods are static, and as such they cannot be overridden using inheritance.
If you want it to apply to every element, why not just have both interfaces implement a 3rd interface with your ToEntity method?
If you can't modify those classes, then consider something akin to the IConverer interface. Have an interface with a method that takes...something, and returns an entity. (It could be generic.) This way you are separating out the code to convert each of those types to entities, much as you would with extension methods.

Categories