extending classes that must be used in an interface - c#

I have created an interface as shown below. The DTO object is a complex value object with 3 parameters.
public interface IOperation
{
DTO Operate(DTO ArchiveAndPurgeDTO);
}
I need people that impliment this interface to be able to inherit from the original Value object and extend it where required.
My assumption was that they could simply inherit the DTO object, add (for example) another property and use it in the same class that impliments this interface.
When I try to use the extended value object, Visual Studio complains that I am no longer implimenting the interface.
How can I impliment this functionality.
Thanks in advance for any ideas, and/or suggestions.
Gineer
Edit:
DTO Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Company.ArchiveAndPurge
{
public class DTO
{
public DTO(String FriendlyID)
{
friendlyId = FriendlyID;
}
private String friendlyId = String.Empty;
public String FriendlyId
{
get { return friendlyId; }
set { friendlyId = value; }
}
private String internalId = String.Empty;
public String InternalyId
{
get { return internalId; }
set { internalId = value; }
}
private Boolean archivedSuccessfully = false;
public Boolean ArchivedSuccessfully
{
get { return archivedSuccessfully; }
set { archivedSuccessfully = value; }
}
}
}
Extended DTO:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Company.MSO.ArchiveAndPurge
{
public class DTO: Company.ArchiveAndPurge.DTO
{
private Boolean requiresArchiving = true;
public Boolean RequiresArchiving
{
get { return requiresArchiving; }
set { requiresArchiving = value; }
}
}
}
Interface Implementation where VS Complains:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Company.ArchiveAndPurge.Contracts;
using Company.ArchiveAndPurge;
namespace Company.MSO.ArchiveAndPurge
{
public class ResolveFriendlyId: IOperation
{
#region IOperation Members
public DTO Operate(DTO ArchiveAndPurgeDTO)
{
ArchiveAndPurgeDTO.InternalyId = ArchiveAndPurgeDTO.FriendlyId;
return ArchiveAndPurgeDTO;
}
#endregion
}
}

As I understand it, you probably had something like:
public class ExtendedOperation : IOperation
{
public ExtendedDTO Operate(ExtendedDTO dto)
{
...
}
}
That doesn't work in two ways:
You can't change the return type when implementing an interface method
You can't change the parameter list when implementing an interface
In particular, you wouldn't be implementing IOperation in a way which would be compatible with code like this:
IOperation operation = new ExtendedOperation();
operation.Operate(new DTO());
I suspect you might want to make the interface generic:
public interface IOperation<T> where T : DTO
{
T Operate(T dto);
}

Use Generics:
public interface IOperation<T> where T : DTO
{
T Operate(T ArchiveAndPurgeDTO);
}

Related

Interface member with "this" keyword

While going through our client's code, I came across below interface in C#, which is having a member with "this" keyword.
public interface ISettings
{
string this[string key] { get; }
}
I am not aware of any such pattern or practice where interface member name starts with "this". To understand more, I checked the implementation of this interface, however still not able to figure out its purpose.
internal class SettingsManager : ISettings
{
public string this[string key]
{
get { return ConfigurationManager.AppSettings[key]; }
}
...
...
}
And here is the caller code:
public static class Utility
{
public static ISettings Handler { get; set; }
public static string Get(string key, string defaultValue)
{
var result = Handler[key];
return Is.EmptyString(result) ? defaultValue : result;
}
}
Unfortunately, I am not able to debug this code to see the things live. But very curious about it. If the implemented code is finally returning a string, then what is the use of "this" keyword out there?
It enables you to do things like:
SettingsManager settings = new SettingsManager();
var setting = settings["my setting"];
A common use is with the List<T> class.
It has the definition:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
// ....
public T this[int index] { get; set; }
// ....
}
This allows you to 'index' the internal values in a similar way to an array.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace test
{
static class Program
{
static void Main()
{
List<string> myStrings = new List<string>();
myStrings.Add("abc");
myStrings.Add("def");
Console.WriteLine(myStrings[0]); // outputs: "abc"
Console.WriteLine(myStrings[1]); // outputs: "def"
Console.Read();
}
}
}
They are indexers, allowing to access your class like an array, in the example your provided you see the usage in this line:
var result = Handler[key];

C# error, member with same name

I writed this code, but, when I try to build, the compiler returns:
1>code.cs(16,16,16,44): error CS0542: 'DataGridViewPercentageColumn': member names cannot be the same as their enclosing type
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Linq;
using System.Xml.Linq;
namespace TestSample
{
internal static class DataGridViewPercentageColumn
{
public class DataGridViewPercentageColumn : DataGridViewColumn
{
public DataGridViewPercentageColumn() : base(new DataGridViewPercentageCell())
{
}
}
public class DataGridViewPercentageCell : DataGridViewTextBoxCell
{
public DataGridViewPercentageCell()
{
this.Style.Format = "0%";
}
}
}
}
How I can solve this, and, why this error happens??
Thanks
You cannot nest two classes with the same names. Your inner class DataGridViewPercentageColumn has the same name like the outer class. You have to rename one of these classes like:
internal class DataGridViewClasses{
public class DataGridViewPercentageColumn : DataGridViewColumn
{
public DataGridViewPercentageColumn() : base(new DataGridViewPercentageCell())
{
}
}
public class DataGridViewPercentageCell : DataGridViewTextBoxCell
{
public DataGridViewPercentageCell()
{
this.Style.Format = "0%";
}
}
}
Btw: You cannot have any other members or properties inside a class named like the class itself.
Your wrapper class has the same name as one of the internal classes.
The issue is DataGridViewPercentageColumn.
The problem here is that you've defined a class within another class, both of which have the same name. Give the internal static class a different name.

Mismatched List Types

I have a base class that has an abstract method which returns a list of itself.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public abstract class baseclass
{
public abstract List<baseclass> somemethod();
}
}
And a descendant that tries to override the base class's method by returning a list of *it*self.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class childclass : baseclass
{
public override List<childclass> somemethod()
{
List<childclass> result = new List<childclass>();
result.Add(new childclass("test"));
return result;
}
public childclass(string desc)
{
Description = desc;
}
public string Description;
}
}
But I get this error:
Error 1 'ConsoleApplication1.childclass.somemethod()':
return type must be 'System.Collections.Generic.List<ConsoleApplication1.baseclass>'
to match overridden member 'ConsoleApplication1.baseclass.somemethod()'
C:\Users\josephst\AppData\Local\Temporary Projects\ConsoleApplication1childclass.cs
0 42 ConsoleApplication1
What's the best approach to have a base class return a list of itself, overriding the base class's method that does the same thing?
Generic i s nice solution, but don't use public abstract List<baseclass> somemethod(); it's bad practice
You should use non-virtual interface pattern
public abstract class BaseClass<T>
{
protected abstract List<T> DoSomeMethod();
public List<T> SomeMethod()
{
return DoSomeMethod();
}
}
public class ChildClass : BaseClass<ChildClass>
{
protected override List<ChildClass> DoSomeMethod(){ ... }
}
When overriding a method, a signature of overriding method must exactly match the signature of the method being overriden. You can achieve what you want with generics:
public abstract class BaseClass<T>
{
public abstract List<T> SomeMethod();
}
public class ChildClass : BaseClass<ChildClass>
{
public override List<ChildClass> SomeMethod() { ... }
}
The error message is self-explanatory. To override the method you need to return a List<baseclass>.
public override List<baseclass> somemethod()
{
List<childclass> result = new List<childclass>();
result.Add(new childclass("test"));
return result;
}

Why cant I expose an implemented interface method?

I've been trying out some n-tier architecture and im really wondering why this code wont compile...
It says the modifier public is not valid for this item. But why not? I need to be able to access the item IRepository.AddString() from a BLL object but it just wont let me make it public....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
BLL myBLL = new BLL();
}
}
interface IRepository<T>
{
void AddString();
}
interface IStringRepo : IRepository<string>
{
List<string> GetStrings();
}
public class BLL : IStringRepo
{
public List<string> FilterStrings()
{
return new List<string>() { "Hello", "World" };
}
public List<string> IStringRepo.GetStrings()
{
throw new NotImplementedException();
}
public void IRepository<string>.AddString()
{
throw new NotImplementedException();
}
}
}
That's an explicitly-implemented member, which is always private.
Remove IStringRepo. from the declaration to create a normal public member that also implements the interface.
Explicitly implemented interfaces cannot use visibility modifiers.
public List<string> IStringRepo.GetStrings()
should be:
public List<string> GetStrings()

Unable to Get data from DA layer. What to do?

While dividing my C# application in layers, I have solved the problem of circular dependency among layers in the following way:
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.Common;
using SolvingCircularDependency.DA;
namespace SolvingCircularDependency.BO
{
public class MyClass : IPersistent
{
private string _message;
public string Message
{
get { return _message; }
set { _message = value; }
}
public bool Save()
{
return MyClassDA.Save(this);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace SolvingCircularDependency.Common
{
public interface IPersistent
{
bool Save();
string Message { get;}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.Common;
namespace SolvingCircularDependency.DA
{
public class MyClassDA
{
public static bool Save(IPersistent obj)
{
Console.WriteLine(obj.Message);
return true;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using SolvingCircularDependency.BO;
namespace SolvingCircularDependency.UI
{
class Program
{
static void Main(string[] args)
{
MyClass myobj = new MyClass();
myobj.Message = "Goodbye Circular Dependency!";
myobj.Save();
Console.ReadLine();
}
}
}
Please take a look at the class MyClassDA in the DA layer and the assembly itself.
How can a MyDA.Get() method return objects of type MyClass when the Data Access layer doesn't know about the MyClass type.
If this design is not efficient, How can I change/modify it?
As far as I can understand you have a bidirectional relationship between your DA and Business layer.
To solve this problem I suggest that you should have 3 layers instead of two. I mean you should have a Model layer that simply model the DB objects ,then you can derive from model classes in your Business layer and add other behaviors like Save method.
Here's what I mean:
//Model Layer
public class UserModel
{
public virtual string Firstname{get;set;}
}
//DataAccess Layer
public class UserDao
{
List<UserModel> GetAll();
}
//BusinessLayer
public class UserDomainModel:UserModel
{
public UserDomainModel(UserModel user,UserDao dao)
{
_user=user;
_dao=dao;
}
public override string FirstName
{
get
{
return _user.FirstName;
}
set
{
_user.FirstName=value;
}
public void Save()
{
_dao.Save(_user);
}
}
}
I'm using a decorator to combine User and UserDao as a domain model object.
One of the reasons people do Persistance Ignorant objects (POCO) is to avoid such a scenario. There is simply no way for the data access layer to have a reference to a class that it doesn't know about - it is much better to have the class not know about the data access.
The only way you can really do this is to implement Get() on User instead of on UserDA. You can do something like this:
public class User {
IGetFromPresistance<User> _userFetcher;
public static IList<User> GetMatching(Specification<User> spec) {
var values = _userFetcher.Find(spec); //Returns a DataRow or IDictionary<string, object>
return new User() {
PhoneNumber = new PhoneNumber(values["phone"].ToString()),
Name = values["name"].ToString(),
};
}
}

Categories