I wrote a nested class which is used as a bag for properties. This class is used as property which I named Properties. I want to extend number of properties by interfaces.
I wrote this example:
public interface IFirst {
int asd { get; set; }
}
public interface ISecond {
int zxc { get; set; }
}
public class MyClass {
public class PropertyClass : IFirst {
public int asd {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
public PropertyClass Properties;
}
public class MyNextClass : MyClass {
public class PropertyClass : MyClass.PropertyClass, ISecond {
public int zxc {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
}
public void test() {
Properties.zxc = 5; // Here is problem
}
}
But in this case I cant to read/write new property zxc.
I think because this still is reading a Properties type from parent class - MyClass.PropertyClass and not MyNextClass.PropertyClass.
I want to extending this without creating new property or hiding existing.
Do you have any suggestions?
You'll have to either ensure that the parent class implements both interfaces, or you'll have to create a new static member in the child class that is of the the nested child type. As you surmise, Properties is declared as being of the parent nested type, and declaring a new type in the child class of the same name that derives from the parent nested type doesn't change that.
Well, depending on what you’re trying to achieve approaches may vary. For instance, using abstract class might feet your needs. Like this:
public interface IFirst
{
int asd { get; set; }
}
public interface ISecond
{
int zxc { get; set; }
}
public abstract class MyAbstractClass<T> where T : class
{
public abstract T Properties {get; set;}
}
public class MyClass : MyAbstractClass<MyClass.PropertyClass>
{
public class PropertyClass : IFirst
{
public int asd
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public override MyClass.PropertyClass Properties
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public class MyNextClass : MyAbstractClass<MyNextClass.PropertyClass>
{
public class PropertyClass : MyClass.PropertyClass, ISecond
{
public int zxc
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
public override MyNextClass.PropertyClass Properties
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public void test()
{
Properties.zxc = 5;
}
}
Related
Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();
I have the following code which is fine...
namespace GenericAbstract
{
public interface INotifModel
{
string Data { get; set; }
}
public interface INotif<T> where T: INotifModel
{
T Model { get; set; }
}
public interface INotifProcessor<in T> where T : INotif<INotifModel>
{
void Yell(T notif);
}
public class HelloWorldModel : INotifModel
{
public string Data { get; set; }
public HelloWorldModel()
{
Data = "Hello world!";
}
}
public class HelloWorldNotif : INotif<HelloWorldModel>
{
public HelloWorldModel Model { get; set; }
public HelloWorldNotif()
{
Model = new HelloWorldModel();
}
}
public class HelloWorldProcessor<T> : INotifProcessor<T> where T : INotif<INotifModel>
{
public void Yell(T notif)
{
throw new NotImplementedException();
}
}
}
As you can see there are 3 interfaces and each of those is implemented.
However, I would like the processor to be implemented like this:
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif<HelloWorldModel>>
{
public void Yell(HelloWorldNotif<HelloWorldModel> notif)
{
throw new NotImplementedException();
}
}
But i get the following error:
The non-generic type 'HelloWorldNotif' cannot be used with type arguments
I want the HelloWorldProcessor to implement INotifProcessor only for HelloWorldNotif...
Can't figure out what I am doing wrong..
For this to work you first have to make INotif<T> co-variant. That means that the Model property has to be read only for the interface (it can still have a public set in an implementation). Then to fix your immediate error you don't put the <HelloWorldModel> after HelloWorldNotif because it's already a INotif<HelloWorldModel>
public interface INotifModel
{
string Data { get; set; }
}
public interface INotif<out T> where T : INotifModel
{
T Model { get; }
}
public interface INotifProcessor<in T> where T : INotif<INotifModel>
{
void Yell(T notif);
}
public class HelloWorldModel : INotifModel
{
public string Data { get; set; }
public HelloWorldModel()
{
Data = "Hello world!";
}
}
public class HelloWorldNotif : INotif<HelloWorldModel>
{
public HelloWorldModel Model { get; set; }
public HelloWorldNotif()
{
Model = new HelloWorldModel();
}
}
public class HelloWorldProcessor<T> : INotifProcessor<T> where T : INotif<INotifModel>
{
public void Yell(T notif)
{
throw new NotImplementedException();
}
}
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif>
{
public void Yell(HelloWorldNotif notif)
{
throw new NotImplementedException();
}
}
Then I guess your implementation would be something like
Console.WriteLine(notif.Model.Data);
As others have said and/or implied out you've already got HelloWorldNotif fully specified. So to translate this:
I want the HelloWorldProcessor to implement INotifProcessor only for
HelloWorldNotif
To C#, I think you mean:
public class HelloWorldProcessor : INotifProcessor<HelloWorldNotif>
{
public void Yell(HelloWorldNotif notif)
{
throw new NotImplementedException();
}
}
I want to create an object that implements an interface and t hen return a reference to it. I've seen how to test whether the object implements an interface but I'm not sure how to do it in the first place.
The interface is as follows:
public interface IInformation
{
string name { get; set; }
string description { get; }
string age { get; set; }
}
And this is where I am trying to create the object, in a new class:
public IInformation NewInformation(string description)
{
}
Any help would be appreciated!
To implement a interface you need to create a class say 'myClass' in my example and use the ':' symbol followed by the interface name. then right click the interface and press the button 'implement interface' this will auto generate all of the methods of your interface but you need to make sure that you change the default implementation from
throw new NotImplementedException();
to whatever logic you wish to use.
public interface IInformation
{
string name { get; set; }
string description { get; }
string age { get; set; }
}
public class myClass : IInformation
{
public string age
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public string description
{
get
{
throw new NotImplementedException();
}
}
public string name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
Then to use the class you will need to do something like this:
public IInformation NewInformation(string description)
{
myClass myInstance = new myClass();
myInstance.description = description;
return myInstance;
}
In writing a data access layer, I want to decouple my public facing API from the concrete db implementations. For example, let's suppose that I want to use either MongoDb or Cassandra for my backing store.
So, what I want is for my C# code to utilize IThingDao through a factory method, etc. The factory will correspond to the actual implementation.
I have some very rudimentary interface and class samples to demonstrate what I hope to achieve. Unfortunately for me, this code generates numerous compile time errors saying the classes don't implement the members of the interface.
The following define my data objects:
public interface IBase
{
Object Id { get; set; }
DateTime CreatedDate { get; set; }
}
public interface IBaseMongoDb : IBase
{
// Common MongoDb related things used by all concrete implementations
}
public interface IBaseCassandra : IBase
{
// Common Cassandra related things used by all concrete implementations
}
public interface IThing : IBase
{
String Name { get; set; }
}
public abstract class AbstractBase
{
public virtual Object Id { get; set; }
public DateTime CreatedDate { get; set; }
}
public abstract class AbstractMongoDbBase : AbstractBase
{
[BsonId]
public override Object Id { get; set; }
// Other specific MongoDb stuff
}
public abstract class AbstractCassandraBase : AbstractBase
{
// Cassandra related stuff
}
public class ThingMongoDbImpl : AbstractMongoDbBase, IThing, IBaseMongoDb
{
public String Name { get; set; }
}
public class ThingCassandraImpl : AbstractCassandraBase, IThing, IBaseCassandra
{
public String Name { get; set; }
}
There are separate base abstracts for MongoDb and Cassandra data objects because each implementation has common features (such as annotations, etc) specific to one versus the other.
Here are the data access interfaces:
public interface IDao<T>
{
T Save( T a_Value );
void Update( T a_Value );
void Delete( T a_Value );
T Find( Object a_Key );
}
public interface IThingDao : IDao<IThing>
{
IThing FindByName( String a_Name );
}
Here are the implementations for MongoDb and Cassandra:
public abstract class AbstractMongoDbDao<T> where T : IBaseMongoDb, new()
{
public T Save( T a_Value )
{
// Save
return a_Value;
}
public void Update( T a_Value )
{
// Update
}
public void Delete( T a_Value )
{
// Delete
}
public T Find( Object a_Key )
{
return new T();
}
}
public class ThingDaoMongoDbImpl : AbstractMongoDbDao<ThingMongoDbImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingMongoDbImpl();
}
}
public abstract class AbstractCassandraDao<T> where T : IBaseCassandra, new()
{
public T Save( T a_Value )
{
// Save
return a_Value;
}
public void Update( T a_Value )
{
// Update
}
public void Delete( T a_Value )
{
// Delete
}
public T Find( Object a_Key )
{
return new T();
}
}
public class ThingDaoCassandraImpl : AbstractCassandraDao<ThingCassandraImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingCassandraImpl();
}
}
For this code, ThingDaoMongoDbImpl and ThingDaoCassandraImpl generate the following compile time errors:
Error 1 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)'. 'generics.decouple.AbstractMongoDbDao<generics.decouple.ThingMongoDbImpl>.Find(object)' cannot implement 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)' because it does not have the matching return type of 'generics.decouple.IThing'.
Error 2 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Delete(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 95 18 Z
Error 3 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Update(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 95 18 Z
Error 4 'generics.decouple.ThingDaoMongoDbImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Save(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 95 18 Z
Error 5 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)'. 'generics.decouple.AbstractCassandraDao<generics.decouple.ThingCassandraImpl>.Find(object)' cannot implement 'generics.decouple.IDao<generics.decouple.IThing>.Find(object)' because it does not have the matching return type of 'generics.decouple.IThing'.
Error 6 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Delete(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 126 18 Z
Error 7 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Update(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 126 18 Z
Error 8 'generics.decouple.ThingDaoCassandraImpl' does not implement interface member 'generics.decouple.IDao<generics.decouple.IThing>.Save(generics.decouple.IThing)' C:\Projects\EDC\modules\EXCHANGES\CAD2CAD.Net\Z\Generics.cs 126 18 Z
Any suggestions on how to get this working?
Thanks
public class ThingDaoMongoDbImpl : AbstractMongoDbDao<ThingMongoDbImpl>, IThingDao
{
public IThing FindByName( String a_Name )
{
// Do the lookup and return value
return new ThingMongoDbImpl();
}
T Save( T a_Value ) { //implement it
}
void Update( T a_Value ) {
//implement it here
}
void Delete( T a_Value ) { // implement it here}
T Find( Object a_Key ) { //implement it}
}
You are getting the compile time error because you did not implement the method of IThingDao interface.
your public interface IThingDao : IDao<IThing>, extends from IDao so you have to implement the methods of IDao<IThing> also
UPDATE
public class ThingCassandraImpl : AbstractCassandraBase, IThing, IBaseCassandra, IThingDao
{
public String Name { get; set; }
public IThing Save(IThing a_Value)
{
throw new NotImplementedException();
}
public void Update(IThing a_Value)
{
throw new NotImplementedException();
}
public void Delete(IThing a_Value)
{
throw new NotImplementedException();
}
public IThing Find(object a_Key)
{
throw new NotImplementedException();
}
public IThing FindByName(string a_Name)
{
throw new NotImplementedException();
}
}
public abstract class AbstractCassandraDao<T> where T : IBaseCassandra,IThingDao, new()
{
public T Save(T a_Value)
{
// Save
return a_Value;
}
public void Update(T a_Value)
{
// Update
}
public void Delete(T a_Value)
{
// Delete
}
public T Find(Object a_Key)
{
return new T();
}
}
public class ThingDaoCassandraImpl : AbstractCassandraDao<ThingCassandraImpl>
{
public IThing FindByName(String a_Name)
{
// Do the lookup and return value
return new ThingCassandraImpl();
}
public IThing Save(IThing a_Value)
{
throw new NotImplementedException();
}
public void Update(IThing a_Value)
{
throw new NotImplementedException();
}
public void Delete(IThing a_Value)
{
throw new NotImplementedException();
}
public IThing Find(object a_Key)
{
throw new NotImplementedException();
}
}
In my project i have 4 layers presentation,BL,DL, and dataObjects. i want to implement abstract factory pattern to get the object i want(doctor/Engineer). Is the code below implementing factory pattern?
public interface IProfessional //The Abstract Factory interface.
{
IProfession CreateObj();
}
// The Concrete Factory class1.
public class DocFactory : IProfessional
{
public IProfession CreateObj()
{
return new Doctor();
}
}
// The Concrete Factory class2.
public class EngFactory : IProfessional
{
public IProfession CreateObj()
{
// IMPLEMENT YOUR LOGIC
return new Engineer();
}
}
// The Abstract Item class
public interface IProfession
{
}
// The Item class.
public class Doctor : IProfession
{
public int MedicalSpecialty
{
get; set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Item class.
public class Engineer : IProfession
{
public string Title{
get;set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Client class.
public class AssignProfession
{
private IProfession _data;
public AssignProfession(DataType dataType)
{
IProfessional factory;
switch (dataType)
{
case DataType.Doc:
factory = new EngFactory();
_data = factory.CreateObj();//from here i will get engineer
break;
case DataType.Eng:
factory = new DocFactory();
_data = factory.CreateObj();//from here i will get doctor
break;
}
}
public IProfession GiveProfessional()
{
return _data;
}
}
//The DataType enumeration.
public enum DataType
{
Doc,
Eng
}
Your code does implement the pattern but not to the full extent which C# allows, in other words - you are not using the important benefits of the C# language.
Here is an example of how you can do it better:
class Program
{
static void Main(string[] args)
{
var myEngineer = ProfessionFactory.CreateProffession<Engineer>();
var myDoctor = ProfessionFactory.CreateProffession<Doctor>();
myEngineer.EnginerringStuff();
myDoctor.HealingPeople();
var myEngineer2 = (Engineer)ProfessionFactory.CreateProffession("Engineer");
//using the other method I still have to cast in order to access Engineer methods.
//therefore knowing what type to create is essential unless we don't care about engineer specific methods,
//in that case we can do:
var myEngineer3 = ProfessionFactory.CreateProffession("Engineer");
//which is useless unless we start involving reflections which will have its own price..
}
public interface IProfessionFactory
{
IProfession CreateObj();
}
public interface IProfession : IProfessionFactory
{
string ProfessionName { get; }
}
public abstract class ProfessionFactory : IProfessionFactory
{
public abstract IProfession CreateObj();
public static T CreateProffession<T>() where T:IProfessionFactory, new()
{
return (T)new T().CreateObj();
}
public static IProfession CreateProffession(object dataObj)
{
if (dataObj == "Engineer")
return CreateProffession<Engineer>();
if (dataObj == "Doctor")
return CreateProffession<Doctor>();
throw new Exception("Not Implemented!");
}
}
public class Engineer : IProfession
{
public string ProfessionName
{
get { return "Engineer"; }
}
public IProfession CreateObj()
{
return new Engineer();
}
public void EnginerringStuff()
{}
}
public class Doctor : IProfession
{
public string ProfessionName
{
get { return "Doctor"; }
}
public IProfession CreateObj()
{
return new Doctor();
}
public void HealingPeople()
{}
}
}
It does seem to have all elements of the pattern, however your IProfession is empty. I am going to assume that is just a placeholder and you are going to fill it in with some methods that represent a behavior that is common to all professions.
Contrast that with the example given in Allen Holub's book
He mentions Collection as the AbstractFactory, Iterator as the abstract product, Tree as the concrete factory and the iterators that are returned as concrete products.