Inheriting from an interface with properties of the same name - c#

I have an interface IProduct and two partial classes SearchedProductInternal and SearchedProductExternal.
These two classes are extending classes coming from 3rd party webservice searches but both return slightly different result types.
I want to use the interface for both so they type returned is the same. I know how to inherit but what do I do to return the "Name" as both the interface and SearchedProductInternal have the same object name?
My Interface is similar to as follows:
public interface IProduct
{
string Name { get; }
string ID { get; }
string DescriptionShort { get; }
string DescriptionLong { get; }
}
My Object SearchedProductInternal has the following properties:
string Name;
int ObjectIdField;
string DescriptionShortField;
string DescriptionLongField;
So my this is where I am inheriting
public partial class SearchedProductInternal : IProduct
{
public string ID
{
get { return ObjectIdField.ToString(); }
}
public string Name
{
//What do I do here?
}
public string DescriptionShort{get { return shortDescriptionField; }
}
public string DescriptionLong {get { return longDescriptionField; }
}
}
I want to the return the name that has been originality assigned in the SearchedProductInternal class but I don't know how to do that because if I just put
return Name
I get a stackoverflow error as it appears to be just keeping calling its self?

I think what you should do here is to explicitly implement the interface, so that you will have both your Name property as defined in the class and the IProduct.Name property from your interface.

You can explicitly implement the interface, like so:
public partial class SearchedProductInternal : IProduct
{
string IProduct.ID
{
get { return ObjectIdField.ToString(); }
}
string IProduct.Name
{
get { return "Interface name"; }
}
string IProduct.DescriptionShort
{
get { return shortDescriptionField; }
}
string IProduct.DescriptionLong
{
get { return longDescriptionField; }
}
// Name property for the class, not the interface
public string Name
{
get { return "Class name"; }
}
}
This way you can differentiate between calls to your interface properties and properties with the same name on your class.
When accessing both properties you can also decide which you want, in the following manner:
var test = new SearchedProductInternal();
Console.WriteLine(test.Name); // returns "Class name"
Console.WriteLine((test as IProduct).Name); // returns "Interface name"

If your SearchedProductInternal already defines the property Name and you're trying to return the value of same Name property, you don't have to do anything.
Don't create one more property named Name. Just get rid of the Name property you added. Everything should work because the class already implemented the contract defined by the interface IProduct.
If you want to return different value from the IProduct.Name property, you can use explicit interface implementation.

You must change the name of the variable in this case Name.
If that was an ambigous sentence then remember it's the same for the PC. Name cannot be two things. but Name and _Name can.
public class SearchedProductInternal : IProduct
{
string _name = "test";
public string Name
{
get
{
return _name;
}
}
}
public interface IProduct
{
string Name { get; }
}

I agree with the above answer. But a minor issue here, we cannot expose the interface member as public, as it causes compile error.
We can have both class level and interface level members. The interface member cannot be accessed by using class instance, which can be accessed only through interface instance.
public interface IProduct
{
string Name { get; }
string ID { get; }
string DescriptionShort { get; }
string DescriptionLong { get; }
}
public partial class SearchedProductInternal : IProduct
{
private string _clsName;
private string _interfaceName;
private string _objectID;
private string _shortDesc;
private string _longDesc;
public SearchedProductInternal(string _cName, string _iName)
{
_clsName = _cName;
_interfaceName = _iName;
}
public string Name
{
get { return _clsName; }
}
string IProduct.Name
{
get { return _interfaceName; }
}
string IProduct.ID
{
get { return _objectID; }
}
string IProduct.DescriptionShort
{
get { return _shortDesc; }
}
string IProduct.DescriptionLong
{
get { return _longDesc; }
}
}
class Program
{
static void Main(string[] args)
{
SearchedProductInternal clsSearchProduct = new SearchedProductInternal("clsName", "interfaceName");
Console.WriteLine(clsSearchProduct.Name);
IProduct interfaceProduct = (IProduct)clsSearchProduct;
Console.WriteLine(interfaceProduct.Name);
Console.ReadLine();
}
}

I am not sure if I just explained this in a way that was not understood but the way that I got this to work was by just using {get;set;}
public partial class SearchedProductInternal : IProduct
{
public string ID
{
get { return ObjectIdField.ToString(); }
}
public string Name {get;set;}
public string DescriptionShort{get { return shortDescriptionField; }
}
public string DescriptionLong {get { return longDescriptionField; }
}
}

Related

Using Interface Derived Classes with NEST and ElasticSearch

I'm trying to use NEST 2.X and Elastic Search for persistent storage of Users. Each User contains a list of Roles which define their permissions inside our platform.
There are several different types of Roles each deriving from a IMediaDetectionRole interface:
public class MediaDetectionUser
{
public string Username { get; set; }
public ICollection<IMediaDetectionRole> Roles { get; set; }
public MediaDetectionUser()
{
Roles = new List<IMediaDetectionRole>();
}
}
public interface IMediaDetectionRole
{
string Name { get; }
string GetDescription();
string GetRoleType {get;}
}
[ElasticsearchType(Name="MediaDetectionAdminRole")]
public class MediaDetectionAdminRole : IMediaDetectionRole
{
public string Name { get { return "Admin"; } }
public string GetDescription() { return "Admin users can create other users within the account"; }
public string GetRoleType { get { return this.GetType().Name; } }
}
[ElasticsearchType(Name = "MediaDetectionManagerRole")]
public class MediaDetectionManagerRole : IMediaDetectionRole
{
public string Name { get { return "Manager"; } }
public string GetDescription() { return "Managers can modify account-level properties"; }
public string GetRoleType { get { return this.GetType().Name; } }
}
[ElasticsearchType(Name = "MediaDetectionCreatorRole")]
public class MediaDetectionCreatorRole : IMediaDetectionRole
{
public string Name { get { return "Creator"; } }
public string GetDescription() { return "Creators can create new Media Detection Profiles"; }
public string GetRoleType { get { return this.GetType().Name; } }
}
I don't have any trouble storing the data in ElasticSearch, but when I go to query the data the data NEST can't figure out the type of these roles. I get:
Could not create an instance of type IMediaDetectionRole.
Type is an interface or abstract class and cannot be instantiated.
Path 'hits.hits[0]._source.roles[0].name', line 1, position 343.
What is the correct way to map nested object data back to the correct class type?
Many thanks!
-Z
Alright, so I guess this is less of a NEST/ES question and more of a JSON.NET question. Apparently the solution to this problem involves telling JSON.NET to provide type hints for each member of the list.
Per #MartijnLaarman's suggestion I added a [JsonProperty] attribute to the Roles property. See below:
public class MediaDetectionUser
{
public string Username { get; set; }
//This JsonProperty helps reference the types during deserialization
[JsonProperty("Roles", ItemTypeNameHandling = TypeNameHandling.All)]
public ICollection<IMediaDetectionRole> Roles { get; set; }
public MediaDetectionUser()
{
Roles = new List<IMediaDetectionRole>();
}
}
Here's an example of the JSON as it appears in the _source inside ElasticSearch:
Roles: [
{
$type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionAdminRole, MediaDetectionFrontend.ServiceModel",
name: "Admin",
getRoleType: "MediaDetectionAdminRole"
},
{
$type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionCreatorRole, MediaDetectionFrontend.ServiceModel",
name: "Creator",
getRoleType: "MediaDetectionCreatorRole"
},
{
$type: "MediaDetectionFrontend.ServiceModel.Types.MediaDetectionEditorRole, MediaDetectionFrontend.ServiceModel",
name: "Editor",
getRoleType: "MediaDetectionEditorRole"
}
]
You can see that the $type attribute now provides the full type descriptor of each element in the List.
Big thanks to #MartijnLaarman who helped me solve this issue even though it really has nothing to do with ElasticSearch and NEST.

Triggering get and set for properties using attribute

I need to build an attribute that will override the getter and the setter of an property. To be more clear, here is how it works today and how it should work using the attribute (the result should be the same).
Old version:
public class A
{
private Handle _handle;
public String StringProp
{
get {
return _handle.GetProperty(PropId.StringProp);
}
set {
_handle.SetProperty(PropId.StringProp, value);
}
}
public int IntProp
{
get {
return _handle.GetProperty(PropId.IntProp);
}
set {
_handle.SetProperty(PropId.IntProp, value);
}
}
}
New version:
public class A
{
private Handle _handle;
[HandleProperty(PropId.StringProp)]
public String StringProp { get; set; }
[HandleProperty(PropId.IntProp)]
public int IntProp { get; set; }
}
The attribute HandleProperty should known to link the getter and setter to _handle.GetProperty and _handle.SetProperty.
I created two enums and some of the fields in one enum were mapped to another enums fields using attributes. I think you can do something like this...
[AttributeUsage(AttributeTargets.Field)]
public sealed class MapsToAttribute : Attribute
{
private string Text;
public string MapsToText
{
get
{
return Text;
}
}
public MapsToAttribute(string mapsToText)
{
Text = mapsToText;
}
public override string ToString()
{
return Text;
}
}

IPersistable Interface - Any trick or hack to change field name

For a class that can be saved in a persistence medium i am creating Interface called IPersistable which is designed to provide a persistenceId.
public interface IPersistable
{
private readonly string persistenceId;
}
Certainly i can't do the above since Interfaces do not allow fields. If it did i would have done below to accomplish it
Public Class Customer
{
private readonly string persistenceId;
Public string UserId
{
get{return persistenceId};
}
Public Customer(string customerId)
{
persistenceId = customerId;
}
}
I already am inheriting a class hence not possible to do multiple inheritance. I could use composition but Interface seems right thing here. Show me a neat hack to do the above instead of adding a property to each class that needs to be persisted.
Question
If possible, can a class that Interfaces with IPersistable change the name of the property( if persistenceId is a property), to something meaningful ?
An interface won't help you if you want to be able to persist existing types such as int or string. Maybe instead of an interface you could use a wrapping class? Something like:
class Persistable<T>
{
public Persistable<T>(string PersistanceId, T Data)
public readonly string PersistanceId;
public readonly T Data;
}
What's wrong with?
public interface IPersistable
{
String PersistenceId { get; }
}
Public Class Customer : IPersistable
{
public string PersistenceId { get; private set; }
public string UserId {
get { return PersistenceId; }
}
.
.
.
}
Try something like this:
public interface IPersistable<TType>
{
TType PersistenceId { get; }
}
public abstract PersistableEntity<TType> : IPersistable<TType>
{
private TType persistenceId;
public TType PersistenceId
{
get { return persistenceId; }
}
public PersistableEntity(TType persistenceId)
{
this.persistenceId = persistenceId;
}
}
public class Customer : PersistableEntity<string>
{
public Customer(string persistenceId)
: base(persistenceId)
{
}
}

In C#, can I hide/modify accessors in subclasses?

I'm not even sure what this principle is called or how to search for it, so I sincerely apologize if it has been brought up before, but the best way to do it is with an example.
class Properties
{
public string Name { get; set; }
}
class MyClass
{
class SubProperties: Properties
{
public override Name
{
get { return GetActualName(); }
set { SetActualName(value); }
}
}
public SubProperties ClassProperties;
private string GetActualName()
{
return SomeFunction();
}
private void SetActualName(string s)
{
ClassProperties.Name = SomeOtherFunction(s);
}
}
The idea is to have any object that instantiates MyClass have a fully accessible property ClassProperties. To that object, it would look exactly like a Properties object, but behind the scenes, MyClass is actually computing and modifying the results of the fields. This method of declaration is obviously wrong since I can't access GetActualName() and SetActualName() from within the SubProperties definition. How would I achieve something like this?
Are you looking for something like this?
abstract class Properties
{
public abstract string Name { get; set; }
}
class MyClass
{
private class SubProperties : Properties
{
private MyClass myClass;
public SubProperties(MyClass myClass)
{
this.myClass = myClass;
}
public override Name
{
get { return this.myClass.GetActualName(); }
set { this.myClass.SetActualName(value); }
}
}
private string name;
public MyClass
{
this.MyClassProperties = new SubProperties(this);
}
public Properties MyClassProperties { get; private set; }
private string GetActualName()
{
return this.name;
}
private void SetActualName(string s)
{
this.name = s;
}
}
You need to pass a reference to a MyClass instance to the SubProperties instance if you want to access MyClass methods from SubProperties.
public virtual string Name { get; set; }

How to implement a property in an interface

I have interface IResourcePolicy containing the property Version. I have to implement this property which contain value, the code written in other pages:
IResourcePolicy irp(instantiated interface)
irp.WrmVersion = "10.4";
How can I implement property version?
public interface IResourcePolicy
{
string Version
{
get;
set;
}
}
In the interface, you specify the property:
public interface IResourcePolicy
{
string Version { get; set; }
}
In the implementing class, you need to implement it:
public class ResourcePolicy : IResourcePolicy
{
public string Version { get; set; }
}
This looks similar, but it is something completely different. In the interface, there is no code. You just specify that there is a property with a getter and a setter, whatever they will do.
In the class, you actually implement them. The shortest way to do this is using this { get; set; } syntax. The compiler will create a field and generate the getter and setter implementation for it.
You mean like this?
class MyResourcePolicy : IResourcePolicy {
private string version;
public string Version {
get {
return this.version;
}
set {
this.version = value;
}
}
}
Interfaces can not contain any implementation (including default values). You need to switch to abstract class.
The simple example of using a property in an interface:
using System;
interface IName
{
string Name { get; set; }
}
class Employee : IName
{
public string Name { get; set; }
}
class Company : IName
{
private string _company { get; set; }
public string Name
{
get
{
return _company;
}
set
{
_company = value;
}
}
}
class Client
{
static void Main(string[] args)
{
IName e = new Employee();
e.Name = "Tim Bridges";
IName c = new Company();
c.Name = "Inforsoft";
Console.WriteLine("{0} from {1}.", e.Name, c.Name);
Console.ReadKey();
}
}
/*output:
Tim Bridges from Inforsoft.
*/
but i already assigned values such that irp.WrmVersion = "10.4";
J.Random Coder's answer and initialize version field.
private string version = "10.4';
You should use abstract class to initialize a property. You can't inititalize in Inteface .

Categories

Resources