Binding two objects of different classes but with similar properties - c#

Is it possible in C# to bind two objects of different classes but with similar properties?
For Example:
class Program
{
static void Main(string[] args)
{
test t = new test();
test2 t2 = new test2();
}
}
public class test
{
public int Number { get; set; }
}
public class test2
{
public int Number { get; set; }
}
So is it possible to say t = t2 somewhow?

You can have both classes implement an interface, if you don't care about what implementation of the interface is used.
For example:
class Program
{
static void Main(string[] args)
{
INumber t = new test();
INumber t2 = new test2();
}
}
public class test : INumber
{
public int Number { get; set; }
}
public class test2 : INumber
{
public int Number { get; set; }
}
public interface INumber
{
int Number { get; set; }
}
An interface is a sort of contract, that provides a definition of what properties and methods an implementing class must define. You can read more on interfaces here.
When your classes implement a shared interface, you're able to to implicitly convert one type into another type, such as in the example above.

Without the addition of extra code, no, you cannot do that.
Even though they are "similar" they are regarded as totally different types by the compiler, and cannot be assigned to each other.
Now, you can include an implicit operator on one (or both) in order to allow implicit casting between the two.
public class test
{
public static implicit operator test(test2 t)
{
return new test(tt.Number);
}
public static implicit operator test2(test t)
{
return new test2(t.Number);
}
public int Number { get; set; }
}
But that is as close as you can get to supporting that syntax.

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; }
}

Dynamic cast behavior in loop

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);

Cast one class object to other class object

I have two classes A and B and I want to cast an instance of A to B. What's the best way?
How Can I make a utility class to perform this task?
public class A
{}
public class B
{}
A good place to start is by reviewing the MSDN documentation on Casting and Type Conversions.
As there's no direct relationship between the two classes, you'll need to write a Conversion Operator. For example:
public class A
{
public int AValue { get; set; }
}
public class B
{
public int BValue { get; set; }
public static explicit operator B(A instanceOfA)
{
return new B { BValue = instanceOfA.AValue };
}
}
You could then write:
A instanceOfA = new A { AValue = 7 };
B instanceOfB = (B)instanceOfA;
// Will output "7"
Console.WriteLine(instanceOfB.BValue);
The documentation I've derived this example from is on MSDN, Using Conversion Operators.
If there was a direct relationship between the two classes, for example B derives from A, for example:
public class A
{
public int Value { get; set; }
}
public class B : A
{
public string OtherValueSpecificToB { get; set; }
}
You wouldn't then need any extra code if you wanted to cast from B to A:
B instanceOfB = new B { OtherValueSpecificToB = "b", Value = 3 };
A instanceOfBCastToA = (A)instanceOfB;
// Will output "3";
Console.WriteLine(instanceOfBCastToA.Value);
// Will not compile as when being treated as an "A" there is no "OtherValueSpecificToB" property
Console.WriteLine(instanceOfBCastToA.OtherValueSpecificToB);

Nested struct as members in a class

I am writing a class which holds 90 integer variables. There are basically 10, but each has 3x3 attributes, making them 90. I'll explain it further.
So the 10 variables I have are: v0, v1, v2, ..., v9. Each of these has three different values, for city, county and state. Also, each of these has three different values for past, present and future.
So, a typical value would be: v3.City.Future or v7.State.Past or v8.County.Present.
I was thinking to implement a class, with 10 structs for each variable, then each of those struct has a three nested structs (for city, county and state) and each of those structs has three integer variables for past, present and future.
This is still in the conceptual phase. I tried to go with the above mentioned approach, but it is not working.
Here is the code snippet:
public class MyClass
{
public MyVariable myvariable;
}
public struct MyVariable
{
public struct National
{
public int Past { get; set; }
public int Present { get; set; }
public int Future { get; set; }
}
...
}
Now when I instantiate the class and access the member (myclass.myvariable.National.Past), it does not get the member.
Here is the answer to this:
public struct PeriodVars
{
public int Past { get; set; }
public int Present { get; set; }
public int Future { get; set; }
}
public struct VarStruct
{
public PeriodVars City;
public PeriodVars County;
public PeriodVars State;
}
Now the class will be:
public class MyClass
{
public VarStruct v0;
public VarStruct v1;
...
}
Once I instantiate an object of the class, I can refer it to like this:
objMyClass.v0.City.Past = 111;
Based on your comment, it looks like you are mixing types and instances:
Assuming your MyVariable looks like the following:
public struct MyVariable
{
public struct National
{
public int Past;
}
public National ValueForNational;
}
myclass.myvariable.National - it is a type (will not compile)
myclass.myvariable.National.Past - it is a member of a type (will not compile)
myclass.myvariable.ValueForNational - is value for a member of MyVariable member inside MyClass' variable (would compile)
myclass.myvariable.ValueForNational.Past - is one that you probably want...
Here is a simple set of classes to accomplish that. I used classes instead of structs as there are some "gotchas" you will need to understand if you use structs.
Unless maybe if you describe "it is not working", I bet that your problem actually is that you are trying to use structs.
public class Foo<T>
{
public T Future;
public T Present;
public T Past;
}
public class Bar
{
public Foo<string> City;
public Foo<string> State;
public Foo<string> Country;
}
public class Top
{
public Bar v0;
public Bar v1;
//...
public Bar v2;
}
There is an initialization missing under struct MyVaribale.
public National national;
internal class Program
{
static void Main(string[] args)
{
var myVar = new MyClass();
myVar.myvariable.national.Past = 1;
}
}
public class MyClass
{
public MyVariable myvariable;
}
public struct MyVariable
{
public National national; // This line is missing. That's why you can't access the members of the 'National' struct.
public struct National
{
public int Past;
public int Present;
public int Future;
}
}

Categories