How can I get access to the Duck Typed proxied object when using impromptu-interface. consider my code that illustrates my example where I get a InvalidCastException when I try to cast my Duck Typed Object to the proxied Object:
using System;
using ImpromptuInterface;
namespace ConsoleApplication1
{
public class Duck
{
public string Says { get; set; }
public int GetNumberOfQuacksPerMinute()
{
return 42;
}
}
public interface IPondBird
{
string Says { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Duck says Quack! Quack!! Quack!!!
var thing = new Duck { Says = "Quack! Quack!! Quack!!!" };
IPondBird myInterface = Impromptu.ActLike(thing);
// ...
// Later on, I want to get access to a proxied object, but I
// get a InvalidCastException here
Duck proxiedObject = (Duck) myInterface;
Console.WriteLine("Duck # quacks per minute: "
+ proxiedObject.GetNumberOfQuacksPerMinute());
}
}
}
Exception is as follows:
An unhandled exception of type 'System.InvalidCastException' occurred
in ConsoleApplication1.exe
Additional information: Unable to cast object of type
'ActLike_IPondBird_c7dd53902ec74f01a3844d4789244ea3' to type
'ConsoleApplication1.Duck'.
You can't. You can think about line
IPondBird myInterface = Impromptu.ActLike(thing);
As something like
public class Wrapper : IPondBird
{
public Wrapper(Duck duck) { ... }
}
IPondBird myInterface = new Wrapper(thing);
That being said you can make the reference to native object part of the contract itself - like:
public interface IPondBird
{
string Says { get; set; }
object NativeObject { get; }
}
public class Duck
{
public string Says { get; set; }
public int GetNumberOfQuacksPerMinute()
{
return 42;
}
public object NativeObject { get { return this; } }
}
IPondBird myInterface = Impromptu.ActLike(thing);
var duck = (Duck)myInterface.NativeObject;
When you use impromptu interface, the generated proxy always has an explicit interface implementation for IActLikeProxy.
IPondBird myInterface = Impromptu.ActLike(thing);
var duck = (Duck)((IActLikeProxy)myInterface).Original;
Related
There's the following interface which defines a packet.
public interface IPacket
{
int Size { get; }
}
There are two implementations, each with its own additional property.
public class FooPacket : IPacket
{
public int Size => 10;
public string FooProperty { get; set; }
}
public class BarPacket : IPacket
{
public int Size => 20;
public string BarProperty { get; set; }
}
The above is library code I have no control over. I want to create a handler for packets
public interface IPacketHandler<T> where T : IPacket
{
void HandlePacket(T packet) ;
}
and create two implementations for the concrete packets.
public class FooPacketHandler : IPacketHandler<FooPacket>
{
public void HandlePacket(FooPacket packet) { /* some logic that accesses FooProperty */ }
}
public class BarPacketHandler : IPacketHandler<BarPacket>
{
public void HandlePacket(BarPacket packet) { /* some logic that accesses BarProperty */ }
}
I'd like to inject a list of packet handlers into a class that manages packet handling so that it can be extended in the future with additional packet handlers.
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandler<IPacket>> packetHandlers)
{
}
}
The trouble I'm having is when creating the injected parameter. I cannot do
var packetHandlers = new List<IPacketHandler<IPacket>>
{
new FooPacketHandler(),
new BarPacketHandler()
};
because I cannot create an instance like so:
IPacketHandler<IPacket> packetHandler = new FooPacketHandler();
I get the error Cannot implicitly convert type 'FooPacketHandler' to 'IPacketHandler<IPacket>. An explicit conversion exists (are you missing a cast?)
I had a look at a similar question: Casting generic type with interface constraint. In that question, OP didn't show the members of the interface, only the definition of it from a generics point of view. From what I can see, if my interface didn't use the generic type parameter as an input, I could make it covariant using the out keyword, but that doesn't apply here.
How do I achieve making manager adhere to the open-closed principle? Is my only recourse changing the interface definition to
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
and then casting to a particular packet in the implementation?
The core of the issue is that ultimately you would call your handler passing a concrete packet (of a concrete type) to it as an argument, even though you hide the argument behind IPacket.
Somehow then, trying to call the HandlePacket( FooPacket ) with BarPacket argument would have to fail, the only question is when/where it fails.
As you already noticed, introducing the generic parameter to the packet handler makes it fail in the compile time and there is no easy workaround over it.
Your idea to drop the generic parameter, i.e. to have
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
is a possible solution. It however pushes the possible failure to the runtime, where you now have to check if a handler is called with inappropriate argument.
What you could also do is to make this runtime check more explicit by introducing a contract for it:
public interface IPacketHandler
{
bool CanHandlePacket(IPacket packet);
void HandlePacket(IPacket packet);
}
This makes it cleaner for the consumer to safely call HandlePacket - assuming they get a positive result from calling CanHandlePacket before.
For example, a possible naive loop over a list of packets and calling your handlers would become
foreach ( var packet in _packets )
foreach ( var handler in _handlers )
if ( handler.CanHandlePacket(packet) )
handler.HandlePacket(packet);
You can solve this with a little bit of reflection.
Firstly, for convenience (and to help slightly with type-safety), introduce a "Tag" interface which all your IPacketHandler<T> interfaces will implement:
public interface IPacketHandlerTag // "Tag" interface.
{
}
This is not really necessary, but it means you can use IEnumerable<IPacketHandlerTag> instead of IEnumerable<object> later on, which does make things a little more obvious.
Then your IPacketHandler<T> interface becomes:
public interface IPacketHandler<in T> : IPacketHandlerTag where T : IPacket
{
void HandlePacket(T packet);
}
Now you can write a PacketHandlerManager that uses reflection to pick out the method to use to handle a packet, and add it to a dictionary like so:
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandlerTag> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
bool appropriateMethodFound = false;
var handlerType = packetHandler.GetType();
var allMethods = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach (var method in allMethods.Where(m => m.Name == "HandlePacket"))
{
var args = method.GetParameters();
if (args.Length == 1 && typeof(IPacket).IsAssignableFrom(args[0].ParameterType))
{
_handlers.Add(args[0].ParameterType, item => method.Invoke(packetHandler, new object[]{item}));
appropriateMethodFound = true;
}
}
if (!appropriateMethodFound)
throw new InvalidOperationException("No appropriate HandlePacket() method found for type " + handlerType.FullName);
}
}
public void HandlePacket(IPacket packet)
{
if (_handlers.TryGetValue(packet.GetType(), out var handler))
{
handler(packet);
}
else
{
Console.WriteLine("No handler found for packet type " + packet.GetType().FullName);
}
}
readonly Dictionary<Type, Action<IPacket>> _handlers = new Dictionary<Type, Action<IPacket>>();
}
If a packet handler passed to the PacketHandlerManager constructor does not implement a method called HandlePacket with a single argument that is assignable from IPacket, it will throw an InvalidOperationException.
For example, attempting to use an instance of the following class would cause the constructor to throw:
public class BadPacketHandler: IPacketHandlerTag
{
public void HandlePacket(string packet)
{
Console.WriteLine("Handling string");
}
}
Now you can call use it thusly:
var packetHandlers = new List<IPacketHandlerTag>
{
new FooPacketHandler(),
new BarPacketHandler()
};
var manager = new PacketHandlerManager(packetHandlers);
var foo = new FooPacket();
var bar = new BarPacket();
var baz = new BazPacket();
manager.HandlePacket(foo);
manager.HandlePacket(bar);
manager.HandlePacket(baz);
Putting it all together into a compilable console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
public interface IPacket
{
int Size { get; }
}
public class FooPacket : IPacket
{
public int Size => 10;
public string FooProperty { get; set; }
}
public class BarPacket : IPacket
{
public int Size => 20;
public string BarProperty { get; set; }
}
public class BazPacket : IPacket
{
public int Size => 20;
public string BazProperty { get; set; }
}
public interface IPacketHandlerTag // "Tag" interface.
{
}
public interface IPacketHandler<in T> : IPacketHandlerTag where T : IPacket
{
void HandlePacket(T packet);
}
public class FooPacketHandler : IPacketHandler<FooPacket>
{
public void HandlePacket(FooPacket packet)
{
Console.WriteLine("Handling FooPacket");
}
}
public class BarPacketHandler : IPacketHandler<BarPacket>
{
public void HandlePacket(BarPacket packet)
{
Console.WriteLine("Handling BarPacket");
}
}
public class PacketHandlerManager
{
public PacketHandlerManager(IEnumerable<IPacketHandlerTag> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
bool appropriateMethodFound = false;
var handlerType = packetHandler.GetType();
var allMethods = handlerType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
foreach (var method in allMethods.Where(m => m.Name == "HandlePacket"))
{
var args = method.GetParameters();
if (args.Length == 1 && typeof(IPacket).IsAssignableFrom(args[0].ParameterType))
{
_handlers.Add(args[0].ParameterType, item => method.Invoke(packetHandler, new object[]{item}));
appropriateMethodFound = true;
}
}
if (!appropriateMethodFound)
throw new InvalidOperationException("No appropriate HandlePacket() method found for type " + handlerType.FullName);
}
}
public void HandlePacket(IPacket packet)
{
if (_handlers.TryGetValue(packet.GetType(), out var handler))
{
handler(packet);
}
else
{
Console.WriteLine("No handler found for packet type " + packet.GetType().FullName);
}
}
readonly Dictionary<Type, Action<IPacket>> _handlers = new Dictionary<Type, Action<IPacket>>();
}
class Program
{
public static void Main()
{
var packetHandlers = new List<IPacketHandlerTag>
{
new FooPacketHandler(),
new BarPacketHandler()
};
var manager = new PacketHandlerManager(packetHandlers);
var foo = new FooPacket();
var bar = new BarPacket();
var baz = new BazPacket();
manager.HandlePacket(foo);
manager.HandlePacket(bar);
manager.HandlePacket(baz);
}
}
}
The output of this is:
Handling FooPacket
Handling BarPacket
No handler found for packet type ConsoleApp1.BazPacket
Thanks for the answers. The solution I ended up with is this, starting with the library code:
public enum PacketType
{
Foo,
Bar
}
public interface IPacket
{
PacketType Type { get; }
}
public class FooPacket : IPacket
{
public PacketType Type => PacketType.Foo;
public string FooProperty { get; }
}
public class BarPacket : IPacket
{
public PacketType Type => PacketType.Bar;
public string BarProperty { get; }
}
The above version is a better approximation of the real thing.
public interface IPacketHandler
{
void HandlePacket(IPacket packet);
}
public abstract class PacketHandler<T> : IPacketHandler where T : IPacket
{
public abstract PacketType HandlesPacketType { get; }
public void HandlePacket(IPacket packet)
{
if (packet is T concretePacket)
{
HandlePacket(concretePacket);
}
}
protected abstract void HandlePacket(T packet);
}
public class FooPacketHandler : PacketHandler<FooPacket>
{
public override PacketType HandlesPacketType => PacketType.Foo;
protected override void HandlePacket(FooPacket packet) { /* some logic that accesses FooProperty */ }
}
public class BarPacketHandler : PacketHandler<BarPacket>
{
public override PacketType HandlesPacketType => PacketType.Bar;
protected override void HandlePacket(BarPacket packet) { /* some logic that accesses BarProperty */ }
}
public class PacketHandlerManager
{
public PacketHandlerManager(Library library, IEnumerable<IPacketHandler> packetHandlers)
{
foreach (var packetHandler in packetHandlers)
{
library.Bind(packetHandler.HandlesPacketType, packetHandler.HandlePacket);
}
}
}
There's some more logic in PacketHandlerManager which I've omitted here. library dispatches packets to handlers, so I don't have to deal with that explicitly after I register handlers using the Bind method.
It's not exactly what I imagined, but it'll do.
I have the following data class and VM class:
public interface IData
{
string Name
{
get;
}
}
public class DataPartial: IData
{
public DataPartial()
{
}
public string Name => "Data partial";
}
public class DataFull : IData
{
public string Name => "Data full";
public DataFull()
{
}
}
public interface IVM
{
IData Data { get; }
}
public interface IVM_partial: IVM
{
new DataPartial Data { get; }
}
public class VM_Partial : IVM_partial
{
public VM_Partial()
{
Data = new DataPartial();
}
public DataPartial Data { get; set; }
IData IVM.Data => Data;
}
public interface IVM_Total:IVM_partial
{
new DataFull Data { get; }
}
public class VM_Total : IVM_Total
{
public VM_Total(IVM_partial dataA)
{
Data = new DataFull();
DataA_interface = dataA;
}
public IVM_partial DataA_interface { get; }
public DataFull Data { get; private set; }
DataPartial IVM_partial.Data => DataA_interface.Data;
IData IVM.Data => Data;
}
public static class RunVM<T, VM>
where T: class, IData
where VM :class, IVM
{
public static T RunMe(VM hi)
{
var vmA = (hi as VM); //how to force-cast this to the VM type??!!
return (T)vmA.Data;
}
}
class Program
{
static void Main(string[] args)
{
VM_Partial partialData = new VM_Partial();
var VMClass = new VM_Total(partialData);
RunVM<DataFull, IVM_Total>.RunMe(VMClass);
RunVM<DataPartial, IVM_partial>.RunMe(VMClass); //here it throws exception because I can't force cast the IVM to IVM_partial
}
}
At the method RunVM<DataPartial, IVM_partial>.RunMe(VMClass);, I want it to return me the DataPartial object, which I know it's there in the object VMClass, but I cannot get it done.
I will get an InvalidCastException when I am at the RunMe method, because the parameter hi is always VMClass, and I can never get it to behave like IVM_partial class. In other words, I can't cast hi to a more basic interface IVM_partial.
How to cast hi to a more basic interface IVM_partial? Is it possible at all, and if not, why not?
It's not the cast that's the problem - it's that you expect the compiler (or runtime) to pick up on the fact that the cast is to a type that declares a new Data property.
This line in RunMe:
return (T)vmA.Data;
... will always use the Data property declared by IVM, because that's the only property the compiler knows about when it's compiling that method. It doesn't matter that you're casting to another interface that contains a new Data property... the cast is about an execution-time check; it doesn't change which Data property the method uses.
It's unclear to me exactly what you're trying to achieve here, but I strongly suspect that you'll need to change tack significantly - maybe by adding another generic type parameter into the mix, maybe by using polymorphism more, or maybe changing the design more radically.
EDIT: This question would be invalid in .NET 4 since it actually works as desired.
I have a Data class that must implement an interface like this:
public interface IData
{
IEnumberable<IOther> OtherList { get; }
IOther AddOther();
void RemoveOtherData(IOther data);
}
But I am stuck with declaring the actual member in Data
public class Data : IData
{
// desired, always return the same reference
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
// Non persistent reference not desirable.
public IEnumerable<IOther> OtherList { get { return _mOtherList.Select(x => x as IOther); } }
List<IOther> _mOtherList = new List<Other>(); // error, type mismatch
List<Other> _mOtherList = new List<Other>(); // error, property return type mismatch
IEnumerable<IOther> _mOtherList = new List<Other>(); // ok, but cannot use List methods without casting.
}
What would be the best solution in this case?
public class Data : IData
{
public IEnumerable<IOther> OtherList { get; private set; }
List<Other> _mOtherList = new List<Other>();
public Data()
{
OtherList=mOtherList.Cast<IOther>();
}
}
On .net 4 IEnumerable<out T> is co-variant. i.e. a class that implements IEnumerable<Other> automatically implements IEnumerable<IOther> too. So could also simply write:
public class Data : IData
{
public IEnumerable<IOther> OtherList { get{return mOtherList;} }
List<Other> _mOtherList = new List<Other>();
}
But I'd avoid that, since it breaks encapsulation and allows outsiders to modify your list.
((List<Other>)MyData.OtherList).Add(...);
Other class must implement IOther interface and you don't need to cast.
When you declare _mOtherList, it's IEnumerable, so you can't use list methods. Declare it as a list.
public class Data : IData
{
List<IOther> _mOtherList = new List<Other>();
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
IOther AddOther()
{
return null;
}
void RemoveOtherData(IOther data){}
}
Your Other class:
class Other : IOther
{
//some members
}
As IEnumerable is covariant this is fine:
public interface IInterface{}
public class ClassA : IInterface{}
public class ClassB
{
private readonly List<ClassA> _classAs;
public IEnumerable<IInterface> Data{ get { return _classAs; } }
}
Maybe I'm overworked, but this isn't compiling (CS0411). Why?
interface ISignatur<T>
{
Type Type { get; }
}
interface IAccess<S, T> where S : ISignatur<T>
{
S Signature { get; }
T Value { get; set; }
}
class Signatur : ISignatur<bool>
{
public Type Type
{
get { return typeof(bool); }
}
}
class ServiceGate
{
public IAccess<S, T> Get<S, T>(S sig) where S : ISignatur<T>
{
throw new NotImplementedException();
}
}
static class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
var access = service.Get(new Signatur()); // CS4011 error
}
}
Anyone an idea why not? Or how to solve?
Get<S, T> takes two type arguments. When you call service.Get(new Signatur()); how does the compiler know what T is? You'll have to pass it explicitly or change something else about your type hierarchies. Passing it explicitly would look like:
service.Get<Signatur, bool>(new Signatur());
Kirk's answer is right on. As a rule, you're not going to have any luck with type inference when your method signature has fewer types of parameters than it has generic type parameters.
In your particular case, it seems you could possibly move the T type parameter to the class level and then get type inference on your Get method:
class ServiceGate<T>
{
public IAccess<S, T> Get<S>(S sig) where S : ISignatur<T>
{
throw new NotImplementedException();
}
}
Then the code you posted with the CS0411 error could be rewritten as:
static void Main()
{
// Notice: a bit more cumbersome to write here...
ServiceGate<SomeType> service = new ServiceGate<SomeType>();
// ...but at least you get type inference here.
IAccess<Signatur, SomeType> access = service.Get(new Signatur());
}
Now my aim was to have one pair with an base type and a type definition (Requirement A). For the type definition I want to use inheritance (Requirement B). The use should be possible, without explicite knowledge over the base type (Requirement C).
After I know now that the gernic constraints are not used for solving the generic return type, I experimented a little bit:
Ok let's introducte Get2:
class ServiceGate
{
public IAccess<C, T> Get1<C, T>(C control) where C : ISignatur<T>
{
throw new NotImplementedException();
}
public IAccess<ISignatur<T>, T> Get2<T>(ISignatur<T> control)
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
}
}
Fine, but this solution reaches not requriement B.
Next try:
class ServiceGate
{
public IAccess<C, T> Get3<C, T>(C control, ISignatur<T> iControl) where C : ISignatur<T>
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
var c = new Signatur();
var bla3 = service.Get3(c, c); // Works!!
}
}
Nice! Now the compiler can infer the generic return types. But i don't like it.
Other try:
class IC<A, B>
{
public IC(A a, B b)
{
Value1 = a;
Value2 = b;
}
public A Value1 { get; set; }
public B Value2 { get; set; }
}
class Signatur : ISignatur<bool>
{
public string Test { get; set; }
public IC<Signatur, ISignatur<bool>> Get()
{
return new IC<Signatur, ISignatur<bool>>(this, this);
}
}
class ServiceGate
{
public IAccess<C, T> Get4<C, T>(IC<C, ISignatur<T>> control) where C : ISignatur<T>
{
throw new NotImplementedException();
}
}
class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
//var bla1 = service.Get1(new Signatur()); // CS0411
var bla = service.Get2(new Signatur()); // Works
var c = new Signatur();
var bla3 = service.Get3(c, c); // Works!!
var bla4 = service.Get4((new Signatur()).Get()); // Better...
}
}
My final solution is to have something like ISignature<B, C>, where B ist the base type and C the definition...
As I mentioned in my comment, I think the reason why this doesn't work is because the compiler can't infer types based on generic constraints.
Below is an alternative implementation that will compile. I've revised the IAccess interface to only have the T generic type parameter.
interface ISignatur<T>
{
Type Type { get; }
}
interface IAccess<T>
{
ISignatur<T> Signature { get; }
T Value { get; set; }
}
class Signatur : ISignatur<bool>
{
public Type Type
{
get { return typeof(bool); }
}
}
class ServiceGate
{
public IAccess<T> Get<T>(ISignatur<T> sig)
{
throw new NotImplementedException();
}
}
static class Test
{
static void Main()
{
ServiceGate service = new ServiceGate();
var access = service.Get(new Signatur());
}
}
I wanted to make a simple and understandable example
if you call a method like this, your client will not know return type
var interestPoints = Mediator.Handle(new InterestPointTypeRequest
{
LanguageCode = request.LanguageCode,
AgentId = request.AgentId,
InterestPointId = request.InterestPointId,
});
Then you should say to compiler i know the return type is List<InterestPointTypeMap>
var interestPoints = Mediator.Handle<List<InterestPointTypeMap>>(new InterestPointTypeRequest
{
LanguageCode = request.LanguageCode,
AgentId = request.AgentId,
InterestPointId = request.InterestPointId,
InterestPointTypeId = request.InterestPointTypeId
});
the compiler will no longer be mad at you for knowing the return type
I received this error because I had made a mistake in the definition of my method. I had declared the method to accept a generic type (notice the "T" after the method name):
protected int InsertRecord<T>(CoasterModel model, IDbConnection con)
However, when I called the method, I did not use the type which, in my case, was the correct usage:
int count = InsertRecord(databaseToMigrateFrom, con);
I just removed the generic casting and it worked.
For those who are wondering why this works in Java but not C#, consider what happens if some doof wrote this class:
public class Trololol : ISignatur<bool>, ISignatur<int>{
Type ISignatur<bool>.Type => typeof(bool);
Type ISignatur<int>.Type => typeof(int);
}
How is the compiler supposed to resolve var access = service.Get(new Trololol())? Both int and bool are valid.
The reason this implicit resolution works in Java likely has to do with Erasure and how Java will throw a fit if you try to implement an interface with two or more different type arguments. Such a class is simply not allowed in Java, but is just fine in C#.
I need to have a wrapper class that exposes some properties of my entity class called ProfileEntity.
I tried doing it by deriving from this entity and then creating properties that return specific entity properties, but it says I cannot cast from ProfileEntity to ProfileEntityWrapper.
When I try to put the return values of a method that returns a 'ProfileEntity' into the wrapper I get the above error.
How do I create such a wrapper class that is castable?
Example
class ProfileEntityWrapper : ProfileEntity
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class Someclass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity; // example of method returning this object
}
}
public class SomeOtherlClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
ProfileEntityWrapper ew = (ProfileEntityWrapper)sc.SomeMethod(); // Cannot do this cast!!!
}
}
You cannot cast an object of ProfileEntity to ProfileEntityWrapper.
var entity = new ProfileEntity(); // this object is only of type ProfileEntity
var wrapper = new ProfileEntityWrapper(); // this object can be used as both ProfileEntityWrapper and ProfileEntity
You probably want to return a ProfileEntityWrapper in SomeMethod():
public class Someclass
{
public ProfileEntity SomeMethod()
{
return new ProfileEntityWrapper(); // it's legal to return a ProfileEntity
}
}
No, that is not possible.
To accomplish this problem you can maybe try this one:
public class ProfileEntity
{
public string ProfileEntityName { get; set; }
}
public class ProfileEntityWrapper
{
public ProfileEntityWrapper(ProfileEntity entity)
{
Entity = entity;
}
public ProfileEntity Entity { get; private set; }
public string Name
{
get
{
return Entity.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
// example of method returning this object
ProfileEntity temp = new ProfileEntity();
return temp;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
//Create a new Wrapper for an existing Entity
ProfileEntityWrapper ew = new ProfileEntityWrapper(sc.SomeMethod());
}
}
If you are allowed to edit the ProfileEntity class, or if the ProfileEntity class is a generated partial class, you could add an interface instead of using a wrapper. You wouldn't need to do any casting with an interface either. Example:
public interface IProfile
{
string Name { get; }
}
public partial class ProfileEntity : IProfile
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
IProfile ew = sc.SomeMethod();
}
}
The IProfile instance will only provide access to the Name property.
This's no correct code from polymorphism aspect.
If we will take the famous polymorphism example when there're base Shape class and Circle, Polygon and Rectangle classes that extend the Shape class, your code will try to cast some shape into circle and as you understand this's invalid casting operation.
So to make this code work you must be sure that SomeClass.SomeMethod() will return instance of ProfileEntityWrapper or perform type check before the casting, like this:
ProfileEntity temp = sc.SomeMethod();
if(temp is ProfileEntityWrapper)
ProfileEntityWrapper ew = (ProfileEntityWrapper) temp;