Can you use interfaces as DataMembers in WCF? - c#

Can you do this?
[DataContract]
public class RegisterEndpointRequest : NotificationRegistrationServiceRequest
{
[DataMember]
public IEndpoint Endpoint { get; set; }
}
Notice the member Endpoint is an interface (IEndpoint), not a class. Will WCF allow this?

I think you can (but I haven't tested it), but you will then need to declare all implementations of that interface with [KnownType]:
[DataContract]
[KnownType(typeof(EndpointImplA))]
[KnownType(typeof(EndpointImplB))]
public class RegisterEndpointRequest : NotificationRegistrationServiceRequest
{
[DataMember]
public IEndpoint Endpoint { get; set; }
}
Each implementing class must have a [DataContract] attribute.

The DataContractAttribute in WCF is not intended for use on an interface: See the documentation here
The answer in this question may give you a better idea why.

Yes, of course you can have interface as DataMember inside DataContract..
Then you have to have specify all the interface implementations in the KnownType attributes...
[DataContract]
[KnownType(typeof(ActivityDC))]
[KnownType(typeof(StepDC))]
[KnownType(typeof(WaveDC))]
public class CampaignDC : AuditedEntityBaseDC
{
[DataMember]
public IList<IActivityDC> Activities { get; set; }

Related

Multiple inheritance by interfaces in Entity Framework?

It is clearly explained here how to achieve "multiple inheritance" in C# by using Interface. However, I wonder, how to achieve the same but in the Entity Framework Code First Workflow.
Provided code to make things clear :
public abstract class DomainObject {
// Every business model must have this fields
public Guid Id {get;set;}
public string SystemCode {get;set;}
}
And here also some optional abstract classes like:
public abstract class MultiTitleObject : DomainObject {
public string TitleRu { get; set; }
public string TitleEn { get; set; }
}
public abstract class ManageableByAdminObject : DomainObject {
public bool isVisibleOnSite {get;set;}
public bool isDeletedByAdmin {get;set;}
}
Let's say that I have class that need to have fields of both MultiTitleObject and ManageableByAdminObject and DomainObject as always rule.
Since C# doesn't support multiple inheritance, I can do the following :
public class ManageableByAdminDomainObject : ManageableByAdminObject {
}
public class ManageableByAdminMultiTitleDomainObject : ManageableByAdminDomainObject {
// Even here it's too complicated...
// What if I need to inherit from 3 or more classes?
}
So the solution I wanted to use is Interface like :
public interface IFieldImitation {
bool isVisibleOnSite ();
}
public class ManageableByAdminObject : IFieldImitation, DomainObject {
public bool isVisibleOnSite () => return true;
}
However, EF does understand abstract classes but not the interfaces.
How should I solve this problem?

Using protobuf-net with inheritance and interface

I have a proto contract as follows:
[ProtoContract]
public MyContract: ContractBase
{
[ProtoMember(1)]
List<IMyDto> MyData
{
get;
set;
}
}
My IMyDto looks like this and its implemenation MyDto
[ProtoInclude(600, typeof(MyDto))]
public interface IMyDto
{
int MyData
{
get;
set;
}
}
[ProtoContract]
public class MyDto :IMyDto
{
[ProtoMember(1)]
int MyData
{
get;
set;
}
}
Finally, my ContractBase looks like this:
[ProtoContract]
[ProtoInclude(500, typeof(MyContract))]
public class ContractBase
{
[ProtoMember(501)]
public string[] ErrorMessages
{
get;
set;
}
}
When I make the web service call, I keep getting the following error:
It was not possible to prepare a serializer for: ContractBase ---> System.InvalidOperationException: No serializer defined for type: IMyDto
Please note that this is a simplified version of code for understanding the problem.
Please let me know what I'm doing wrong?
Any help is much appreciated.
Thanks.
Mark IMyDto with [ProtoContract] attribute.
It worked for me, after I've done that.
Getting Started documentation says, it is necessary every type participating in serialization is marked so.

C# implement interface with properties that are interface.

I am using EF code first to generate my db and I do need concrete property for ICollection of EF entity models. I am writing a data access layer ( Using generic classes) however hit the following road block with using interfaces in my generic class as shown below.
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass
{
ICollection<ITestClassProp> TestProp { get; set; }
}
public class TestClass : ITestClass
{
// works
//public ICollection<ITestClassProp> TestProp { get; set; }
// does not work
public ICollection<TestClassProp> TestProp { get; set; }
}
Am I totally mis using the interfaces? why cant I use TestClassProp instead of ITestClassProp?
Thanks
When you implement an interface, you have to implement the methods/properties of that interface with the same signature. Since the interface declares ICollection<ITestClassProp> TestProp { get; set; } then your TestClass must also declare ICollection<TestClassProp> TestProp { get; set; }.
The reason this is necessary is that other classes that know about the interface but not the concrete class are expecting the property to be ICollection<ITestClassProp> and not ICollection<TestClassProp>.
As you've currently written your code, you are not satisfying the requirement you've imposed via your ITestClass interface, which is to have a property of ICollection<ITestProp>.
One way around this is to actually make ITestClass generic, but provide a generic constraint of ITestClassProp
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass<T> where T : ITestClassProp
{
ICollection<T> TestProp { get; set; }
}
public class TestClass : ITestClass<TestClassProp>
{
public ICollection<TestClassProp> TestProp { get; set; }
}
This allows you to provide any concrete type that implements ITestProp to your ICollection.
Simply, the interface declares a property of type ICollection, but you implement it as ICollection, which has a totally different signature.
You might want to read up on covariance and contravariance also.

C#, abstract superclass implementing a concrete variable defined by the subclass?

I have a system that performs operations on lots of Things, these can be considered to be hardware devices accessible over a communication channel.
I use a manager construct that accepts tasks for single Things. Now, there are at least three types of Thing and they have slightly different properties associated with them. The manager must know about these extra properties as they are needed to perform any operation correctly (some Things must have their X foo'd instead of their Y etc...).
At the moment I have separate manager class for each type of thing. This causes a good deal of duplication as the Things are mostly similar.
It would be good if I could have an abstract manager that implements a good deal of the functionality and then each concrete implementation can supply the little extra bits.
Here is a greatly simplified example:
public abstract class ThingManager
{
private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;
public virtual AddNewThingTask(<params>)
{
??ThingTask?? NewTask = new ??ThingTask??(<params>);
_ThingTaskQueue.Add(NewTask);
Monitor.Pulse(_NewDataToProcess);
}
/* Implemented by the concrete, will depend on the type of ??ThingTask?? */
public abstract GetSomeTaskParameterForAThing(Guid thingID)
}
public class ThingTask
{
public enum ThingOperation
{
Foo,
Bar
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
}
public class AdvancedThingTask
{
public enum ThingOperation
{
Foo,
Bar,
Baz
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
public Boolean EnableFrobber { get; set; }
}
As you can see I need some way, when defining the concrete ThingManager to have ??ThingTask?? be either a ThingTask or an AdvancedThingTask. It would then be up to the concrete to make use of the extra properties when implementing the abstract methods.
Using an interface for ??ThingTask?? wouldn't work because the properties would have to be declared in the interface and each one has different properties available.
I get the feeling I'm missing something very obvious as to how to do this cleanly, hopefully someone can help :)
use generics rather than a pure abstract class, someting along the lines of:
public abstract class ThingManager<T> where T : ThingTask
dependant on your full implementation I doubt if this will need to remain abstract
Is there any reason you don't make AdvancedThingTask a subclass of ThingTask?
public class ThingTask
{
public virtual string Name { get; set; }
public virtual ThingType Type { get; set; }
public virtual ThingOperation Operation { get; set; }
public virtual void DoThing() { /*Do something associated with ThingTask*/ }
}
public class AdvancedThingTask : ThingTask
{
public bool EnableFrobber { get; set; }
public override void DoThing() { /*Do something associated with AdvancedThingTask*/ }
}
The only problem I see with this is that ThingOperation will need to be declared outside of the classes so that it can have all the values, or some other solution that will enable classes to have values that aren't in the base declaration. That problem may be solved by putting what you want to do as virtual methods in the classes.
P.S. Why do your properties start with underscores? Usually that's reserved for private variables.

Hide public Property when exposed through web service

I would like to prevent a property from being exposed via my WCF web service. I tried adding the XmlIgnore attribute bug that didn't work. We are using .NET 3.5. WCF.
This doesn't work:
public class MyClass
{
public string S1 { get; set; }
[XmlIgnore]
public string S2NotExposed { get; set; }
}
Mark your class with the [DataContract] attribute from the DataContractAttribute Class , then mark only the properties you want to expose with the [DataMember] attribute from the DataMemberAttribute Class.

Categories