I've created three interfaces - IUser, ICostCenter, IDepartment. IUser and IDepartment are properties of ICostCenter.
public interface ICostCenter
{
IDepartment Department { get; set; }
User.IUser CostCenterHead { get; set; }
}
The class implementing ICostCenter will be used in the DbContext for my db.
public class tblCostCenter : WorkingInterface.Interface.Organization.ICostCenter
{
public tblCostCenter()
{
this.ID = Guid.NewGuid().ToString();
}
public string ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
private WorkingInterface.Interface.User.IUser CostCenterHead { get; set; }
public string UserID { get; set; }
[ForeignKey("UserID")]
public Model.tblUser UserObject
{
get { return (Model.tblUser)this.CostCenterHead; }
set { this.CostCenterHead = value; }
}
private WorkingInterface.Interface.Organization.IDepartment Department { get; set; }
public string DepartmenID { get; set; }
[ForeignKey("DepartmenID")]
public Model.tblDepartment DepartmentObject
{
get { return (Model.tblDepartment)this.Department; }
set { this.Department = (Model.tblDepartment)value; }
}
}
I'm getting an error because I made the IUser and IDepartment properties private. How can I properly implement the interface? I want these properties to be hidden.
The interface is declared explicitly as public, that means that all the members declared in that interface MUST be public
So you need to declare both of these properties as public:
public WorkingInterface.Interface.User.IUser CostCenterHead { get; set; }
public WorkingInterface.Interface.Organization.IDepartment Department { get; set; }
NOTE: these have been declared as implicit implementations, so they are available to all contexts. If you want to hide them from general use, you can use explicit implementation.
Because you tried to use private accessibility, I assume you generally want to hide these properties from view, you can do this and still honor the interface contract by using explicit implementation syntax:
WorkingInterface.Interface.User.IUser ICostCenter.CostCenterHead { get; set; }
WorkingInterface.Interface.Organization.IDepartment ICostCenter.Department { get; set; }
They are still public but can only be accessed by first casting the object to the specific interface type explicitly.
tblCostCenter obj = new tblCostCenter();
...
// this wont work:
Console.WriteLine(obj.CostCenterHead);
// instead you will have to cast the object first
Console.WriteLine((obj as ICostCenter)).CostCenterHead);
// or if the local variable was an ICostCenter
ICostCenter costObj = obj;
Console.WriteLine(costObj.CostCenterHead);
...
// Pattern matching can also be helpful in these scenarios
if (obj is ICostCenter cc)
Console.WriteLine(cc.CostCenterHead);
If you want to use explicit declaration in your class you could try this:
WorkingInterface.Interface.User.IUser ICostCenter.CostCenterHead { get; set; }
public string UserID { get; set; }
[ForeignKey("UserID")]
public Model.tblUser UserObject
{
get { return ((ICostCenter)this).CostCenterHead as Model.tblUser; }
set { ((ICostCenter)this).CostCenterHead = value; }
}
WorkingInterface.Interface.Organization.IDepartment ICostCenter.Department { get; set; }
public string DepartmenID { get; set; }
[ForeignKey("DepartmenID")]
public Model.tblDepartment DepartmentObject
{
get { return ((ICostCenter)this).Department as Model.tblDepartment; }
set { ((ICostCenter)this).Department = value; }
}
this only works if:
Model.tblDepartment : IDepartment
Model.tblUser : User.IUser
Related
On one hand I have a list of capabilities, for example:
public interface ICapability
{
public string Name { get; }
}
public class RangeCapability<T> : ICapability
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
On the other hand I have a list of requirements
public interface IRequirement
{
public string Name { get; }
}
public class Requirement<T> : IRequirement
{
public string Name { get; set; }
public T Value { get; set; }
}
Both capability list may contain capabilities of different types T and requirement list may contain requirements of different types. The important thing is that if for a given name the underlying types match I should check if value is between min and max (for range class) or in a set like in the example below:
public class Entity
{
List<ICapability> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement> requirements)
{
foreach(var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement .Name);
//how to check if here if types match and if req. within range or in collection?
}
}
}
I am not sure how to match generic types of two different classes and then do the check suitable for the apropriate implementation (is within range/is present in set). Can somebody point me in the right direction how could I make it work?
I believe this is what you're looking for. Make the interfaces generic and also make the Entity class generic.
public interface INamed<T>
{
string Name { get; }
}
public interface ICapability<T> : INamed<T>
{
}
public class RangeCapability<T> : ICapability<T>
{
public string Name { get; set; }
public T Min { get; set; }
public T Max { get; set; }
}
public class SetCapability<T>
{
public string Name { get; set; }
public HashSet<T> Set { get; set; }
}
public interface IRequirement<T> : INamed<T>
{
}
public class Requirement<T> : IRequirement<T>
{
public string Name { get; set; }
public T Value { get; set; }
}
public class Entity<T>
{
List<ICapability<T>> Capabilities { get; set; }
public bool IsSatisfying(List<IRequirement<T>> requirements)
{
foreach (var requirement in requirements)
{
var capability = Capabilities.FirstOrDefault(x => x.Name == requirement.Name);
//how to check if here if types match and if req. within range or in collection?
if(capability is INamed<T>)
{
Console.WriteLine("types match");
}
}
}
}
I am invoking a method in my constructor like below.Is this the right way to do to set properties based on some validations.Please suggest.
public class Asset
{
public Asset(string id)
{
SetStorageId(id);
}
public string AssetId { get; set; }
public string UtilId { get; set; }
public string MappingId { get; set; }
public bool IsActive { get; set; }
private void SetStorageId(string id)
{
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
AssetId = id;
}
else
{
UtilId = id;
}
}
}
In my opinion your design should be like below,
You should abstract common items to base class and create specific class inheriting this,
and decide from client(consumer) which instance do you need and construct it
public class AssetBase
{
public string MappingId { get; set; }
public bool IsActive { get; set; }
}
public class Asset : AssetBase
{
public string AssetId { get; set; }
}
public class Util : AssetBase
{
public string UtilId { get; set; }
}
static void Main(string[] args)
{
string id = Console.ReadLine();
if (Regex.Match(id, "^[A-Z][a-zA-Z]*$").Success)
{
Asset asset = new Asset();
asset.AssetId = id;
}
else
{
Util util = new Util();
util.UtilId = id;
}
}
simply try this
public class Asset
{
private string id;
public string AssetId { get; set; }
public string UtilId { get; set; }
public string Id
{
set
{
if (Regex.Match(value, "^[A-Z][a-zA-Z]*$").Success)
{
this.id = value;
}
else
{
UtilId = value;
}
}
get
{
return id;
}
}
}
When you create a property in c#, a private variable is created for that property on compile time. When you try to set the Id property in the code above the Id you pass goes into the value keyword and you can perform your validations on the value keyword and set your property accordingly.
No need to complicate your code with set methods, constructors or deriving classes
or you can even use data annotations which is a more elegant way https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx#Properties
using System.ComponentModel.DataAnnotations;
public class Asset
{
[RegularExpression("^[A-Z][a-zA-Z]*$")]
public string Id { get; set; }
}
It's not wrong. It can possibly grow to be a little confusing. Maybe you can make it clearer by moving the bod of SetStorageId to the constructor. Perhaps there is no need to complicate with subclassing, relative to other code within the project.
I am trying to implement a hierarchical inheritance structure in Entity Framework, specifically for settings. For example, lets say we have user preferences:
public class StorePreference: Preference { }
public class UserPreference : Preference { }
public class Preference {
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
}
public enum ContactMethod {
SMS,
Email
}
I'd like it so that if I lookup the user's preferences. If the user doesn't exist or the property value is null, it looks up the parent (store) default preferences.
Ideally, i'd like it to work similar to abstract inheritance:
public class UserPreference : StorePreference {
private string _backgroundColor;
public string BackgroundColor {
get {
if (this._backgroundColor == null)
return base;
return this._backgroundColor;
}
set { this._backgroundColor = value; }
}
}
If I were to write this as a SQL query, it'd be a CROSS APPLY with a CASE statement:
SELECT
CASE WHEN User.BackgroundColor == null THEN Store.BackgroundColor ELSE User.BackgroundColor END BackgroundColor,
CASE WHEN User.ContactMethod == null THEN Store.ContactMethod ELSE User.ContactMethod END ContactMethod
FROM UserPreference User
CROSS APPLY StorePreference Store
WHERE UserPreference.UserId = #UserId
Is there a way I can achieve loading this in EF?
In your base class add default property values:
public class Preference {
public string BackgroundColor { get; set; } = "Red";
public ContactMethod ContactMethod { get; set; } = ContactMethod.SMS;
}
Something like this to set from database:
public class StorePreference : Preference { }
public class UserPreference : Preference { }
public class Preference {
public Preference() {
BackgroundColor = DefaultPreference.BackgroundColor;
ContactMethod = DefaultPreference.ContactMethod;
}
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
public DefaultPreference DefaultPreference { get; set; }
}
public class DefaultPreference {
public string BackgroundColor { get; set; }
public ContactMethod ContactMethod { get; set; }
}
As long as the properties are public, entity won't have a problem pulling the data from another table as the default. You would need to create a private field to hold the data if you used a setter:
public class ChildTable : EntityBase {
private string _someCategory;
[Key]
[Column(name: "CHILD_ID")]
public override int Id { get; protected set; }
[Column(name: "SOME_CATEGORY")]
public string SomeCategory {
get { return _someCategory; }
set { _someCategory = value ?? ParentTable.SomeCategory; }
}
[ForeignKey("ParentTable")]
[Column(name: "PARENT_ID")]
public int ParentTableId { get; set; }
public virtual ParentTable ParentTable { get; set; }
}
This is just an alternative to a constructor, if you need more control over the setter logic, otherwise Austin's answer would be simpler to implement
I am getting a rather weird casting error. Here is the code:
public class OrganizationLocation : IOrganizationLocation
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public interface IOrganizationLocation
{
string Name { get; }
}
public class Organization : IOrganization
{
public Guid Id { get; set; }
public string Alias { get; set; }
public virtual ICollection<OrganizationLocation> Location { get; set; }
public ICollection<IOrganizationLocation> Locations
{
get
{
return (ICollection<IOrganizationLocation>) Location;
}
}
}
public interface IOrganization
{
string Alias { get; }
ICollection<IOrganizationLocation> Locations { get; }
}
now when I try to run this via a service (backend data layer is EF6), the "Location" variable has all the values, however, the "Locations" variable fails to cast. If I try to do a safe cast, it comes back as null every time.
I'm not understanding why would the cast fail? It has same fields, both are ICollection Type, so why do I get a HashSet?
The reason why I am doing it this way is because for EF6 framework to be able to treat this class as a table it needs to have a concrete type and a public get/set. However, I do not wish to expose that, so I use interface instead and then inject the class when the interface is called. This way I only expose get method and on top of it I only expose interface layers.
Unable to cast object of type 'System.Collections.Generic.HashSet`1[Namespace.OrganizationLocation]' to type 'System.Collections.Generic.ICollection`1[Namespace2.IOrganizationLocation]'.
I was able to resolve this by changing the code to the following:
public class OrganizationLocation : IOrganizationLocation
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public interface IOrganizationLocation
{
string Name { get; }
}
public class Organization : IOrganization
{
public Guid Id { get; set; }
public string Alias { get; set; }
public virtual ICollection<OrganizationLocation> Location { get; set; }
public IEnumerable<IOrganizationLocation> Locations => Location
}
public interface IOrganization
{
string Alias { get; }
IEnumerable<IOrganizationLocation> Locations { get; }
}
I have the below code in my Application.
public class GeneralInfo
{
private string _id;
private string _name;
public string id
{
set
{
_id = value;
}
get
{
return _id;
}
}
public string name
{
set
{
_name = value;
}
get
{
return _name;
}
}
}
public class SecureInfo
{
private string _password;
public string password
{
set
{
_password = value;
}
get
{
return _password;
}
}
}
public class User
{
}
I need to apply multiple inheritance in the above code ie. the classes GeneralInfo,SecureInfo properties should be accessible in the user class.
I know using interface Multiple inheritance can be achieved. But i need to define the properties in the base class which is restricted in Interface.
How I can achieve this?
C# does not support multiple inheritance. However you can achieve this via multiple interfaces.
public interface ISecureInfo
{
}
public interface IGeneralInfo
{
}
public class UserClass : ISecureInfo, IGeneralInfo {
}
You probably better off encapsulating the data in the class rather than trying to use something to do multiple inheritance here. See this question for some arguments for this.
You can achieve this through interface based inheritance:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
// Implementation of IGeneralInfo
public String Id { get; set; }
public String Name { get; set; }
// Implementation of ISecureInfo
public String Password { get; set; }
}
Or, going one step further, through composition:
public interface IGeneralInfo
{
String Id { get; set; }
String Name { get; set; }
}
public class GeneralInfo : IGeneralInfo
{
public String Id { get; set; }
public String Name { get; set; }
}
public interface ISecureInfo
String Password { get; set; }
}
public class SecureInfo : IGeneralInfo
{
public String Password { get; set; }
}
public class User : IGeneralInfo, ISecureInfo
{
private GeneralInfo generalInfo = new GeneralInfo();
private SecureInfo secureInfo = new SecureInfo();
public String Id {
get { return generalInfo.Id; }
set { generalInfo.Id = value; }
}
public String Name {
get { return generalInfo.Name; }
set { generalInfo.Name = value; }
}
public String Password {
get { return secureInfo.Password; }
set { secureInfo.Password = value; }
}
}
From your sample description, encapsulation might be what you might want to use:
public class Info{
GeneralInfo general;
SecureInfo secure;
...
}
You cannot do multiple inheritance in C# because it is not supported like C++. In C# you can use interfaces for it and implement method and properties. For sample, you could have a base class
public abstract class Entity
{
public string Name { get; set; }
}
You also could have some interfaces:
public interface IPrint
{
void Print();
}
public interface IGenerate
{
void Generate();
}
And use it like multiples inheritance (but it is not, it is just a single inheritance and interfaces)
public class User : Entity, IPrint, IGenerate
{
public void Print()
{
// some code
// here you could access Name property, because it is on base class Entity
}
public void Generate()
{
// some code
}
}
And you could instance it using the abstractions:
Entity e = new User();
IPrint p = new User();
IGenerate g = new User();
User u = new User();
If you need implementations, you could do a hiearachy inherits, for sample:
User inherit from Person that inherit from Entity.
public class Entity
{
public int Id { get; set; }
public void Method()
{
// some code
}
}
public class Person : Entity
{
public string Name { get; set; }
public void AnotherMethod()
{
// some code
}
}
public class User : Person
{
public string Password { get; set; }
public bool CheckUser(string name, string passworkd)
{
// some code
}
}
I think the best would be to seperate the implementation of the interfaces and the real class you have at the end.
What I mean is something like the Bridge Pattern.
Your class (that will implement several interfaces) will just deleagte the method calls to the real implementation, that you can have in a seperate place and only once.
You could also use an approach like this. You would get to the same point than if you would be using multiple inheritance. That way, you could inherit only Entity if you don't need the SecureInfo stuff (i.e. for books and other stuff). Still, I think composition would do better in this case as others say...
class User : SecuredEntity { }
abstract class SecuredEntity : Entity, ISecureInfo
{
public string Password { get; set; }
}
abstract class Entity : IGeneralInfo
{
public string ID { get; set; }
public string Name { get; set; }
}
interface IGeneralInfo
{
string ID { get; set; }
string Name { get; set; }
}
interface ISecureInfo
{
string Password { get; set; }
}