I have multiple interfaces that my objects can implement. I am wondering if there is a way to "cascade" one extension method into another while using the same method name. I may be looking at this all wrong, but here is an example:
public interface IBaseDto
{
int Id {get;set;}
string CreatedByFullName {get;set;}
}
public interface IDocumentDto
{
List<ContactDto> Subscriptions {get;set;}
}
public class ContactDto: IBaseDto
{
public int Id {get;set;}
public string CreatedByFullName {get;set;}
public string FirstName {get; set}
public string LastName {get;set;}
}
public class MeetingDto: IDocumentDto
{
public int Id {get;set;}
public string CreatedByFullName {get;set;}
public List<ContactDto> Subscriptions {get;set;}
}
So, let's say I want to convert the DTOs into entities using an extension method. An example would be MeetingDto.ToEntity();
I am trying to think if I can write part of the extension method for an IBaseDto, another for the IDocumentDto and then for each concrete implementations for just their own properties. When I call MeetingDto.ToEntity() it would first hit the meeting extension method and call the IDocumentDto version, fill in what it needed, and then the IDocumentDto would call the IBaseDto. I hope this makes sense.
UPDATE:
I came up with this and it works pretty well:
public static TBaseDto ToEntity<TBridgeDto>(this TBaseDto dto) where TBaseDto: IBaseDto
{
...
return dto;
}
public static TDocumentDto ToEntity<TDocumentDto>(this TDocumentDto dto, IDocumentDto currentDto) where TDocumentDto : IDocumentDto
{
...
return dto.ToEntity();
}
public static MeetingDto ToEntity(this RfiDto dto)
{
...
return dto.ToEntity(dto)
}
Like this?
public static class Helper
{
public static void ToEntity(this MeetingDto source)
{
Console.WriteLine ("MeetingDto.ToEntity");
//Do Stuff
(source as IDocumentDto).ToEntity();
}
public static void ToEntity(this ContactDto source)
{
Console.WriteLine ("ContactDto.ToEntity");
//Do Stuff
(source as IBaseDto).ToEntity();
}
public static void ToEntity(this IDocumentDto source)
{
Console.WriteLine ("IDocumentDto.ToEntity");
//Do Stuff
foreach (var element in source.Subscriptions)
{
element.ToEntity();
}
}
public static void ToEntity(this IBaseDto source)
{
Console.WriteLine ("IBaseDto.ToEntity");
//Do Stuff
}
}
Yes you can..... just cast to the interface you want...
eg
interface I1
{
int Id { get; set; }
}
public interface I2
{
string Name { get; set; }
}
public class Blah : I1, I2
{
public int Id { get; set; }
public string Name { get; set; }
}
static class ExtendIt
{
public static void ToEntity(this I1 x)
{
x.Id = 1;
}
public static void ToEntity(this I2 x)
{
x.Name = "hello";
}
public static void ToEntity(this Blah x)
{
(x as I1).ToEntity();
(x as I2).ToEntity();
}
}
Extension methods are static, and as such they cannot be overridden using inheritance.
If you want it to apply to every element, why not just have both interfaces implement a 3rd interface with your ToEntity method?
If you can't modify those classes, then consider something akin to the IConverer interface. Have an interface with a method that takes...something, and returns an entity. (It could be generic.) This way you are separating out the code to convert each of those types to entities, much as you would with extension methods.
Related
I need to have something like this. So a class that implements this Interface needs to get a property with the same type as the class.
Is this even possible, ifso how? I'm using .net 6.
public interface IProperty
{
public typeof(this) parameter { get; } // doesn't work, can't use typeof()
}
public class clsResourceProperty : IProperty
{
public clsResourceProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public clsInterfaceProperty parameter { get; }
}
I know how to use generic interfaces, and with the second example it works, but clsResourcePropertyGeneric: IPropertyGeneric looks strange. And doens't work for the application i need.
public interface IPropertyGeneric<T>
{
public T parameter { get; }
}
public class clsResourcePropertyGeneric: IPropertyGeneric<clsResourcePropertyGeneric>
{
public clsResourcePropertyGeneric parameter { get; }
}
public class clsInterfacePropertyGeneric: IPropertyGeneric<clsInterfacePropertyGeneric>
{
public clsInterfacePropertyGeneric parameter { get; }
}
In the application i need, i need to have a class containing a list of this interface. So something like this:
public class clsState
{
public List<IProperty> data {get; private set;}
public clsState(List<IProperty> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
But this doesn't work with the generic interface. I need to make a class containing a list of this interface, where i define the generic type T. But this list can't contain ALL classes which implement this interface
public class clsState<T>
// need to add T here to use it in the list, but the list needs to contain ALL implementing class types, not only 1
{
public List<IProperty<T>> data {get; private set;}
public clsState(List<IProperty<T>> data)
{
this.data = data;
}
public void logic()
{
foreach(var d in data)
{
//do something with d.parameters
}
}
}
I found this link, but this is from 7 years ago, so maybe there is some evolution in this aspect?
You can use the interface as your property type, as in:
public interface IProperty
{
public IProperty parameter { get; }
}
public class clsResourceProperty : IProperty
{
public IProperty parameter { get; }
}
public class clsInterfaceProperty : IProperty
{
public IProperty parameter { get; }
}
As for having a collection of the interfaces, it is possible to collect all of the classes for a particular type or interface. This is from a piece of code in one of my libraries. It doesn't do exactly what you're after, but it might be a step towards your final solution.
private static Type[] strategyTypes;
private readonly static Type[] obsoleteTypes = new Type[]
{
};
static StrategyRepository()
{
strategyTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => t.BaseType == typeof(Strategy))
.Except(obsoleteTypes)
.ToArray();
}
This question might be a more direct answer to that part of your question: Getting all types that implement an interface
I have class A and B (just sample)
public class A
{
public long Id { get; set; }
public string Name { get; set; }
}
public class B : A
{
public B(long id,string name)
{
}
}
And want to do
var b = new B(100, "myName");
Save(b);
I have a save method that I want to allow only types inherited from A Class and also have uses the constructor that accept two parameters
// I know this will work if my Class B has public B() {},
//but not sure how to restrict to have only the once which accept constructor with two parameters
private void Save<T>(T target) where T : A, new ()
{
//do something
}
There's nothing in the C# type system that will enforce that constraint. You could use the reflection APIs to verify at runtime.
Another alternative would be to specify a factory:
interface IFactory<T> where T : A {
T Construct(object param1, object param2)
}
class BFactory : IFactory<B> {
public B Construct(object param1, object param2) {
return new B(param1, param2);
}
}
void Save<T>(T target, IFactory<T> tFactory) where T : A {
T newT = tFactory.Construct(a, b);
}
Generic constraints do not support constructors with parameters. Mostly a factory or creation function is used ( e.g. Is there a generic constructor with parameter constraint in C#? ), but since the object is created beforehand and you only want to filter which objects are allowed, a safer method is to implement an (empty) interface and use that as constraint:
public class A
{
public long Id { get; set; }
public string Name { get; set; }
}
public class B : A, IAmB
{
public B(long id,string name)
{
}
}
public interface IAmB{}
That way the constraint would be:
private void Save<T>(T target) where T : A, IAmB
{
}
I'm trying to accomplish some hacking & slashing and was wondering how to approach the following.
There are 2 interfaces defined:
public interface IBase
{
string Name { get; }
void Run();
}
public interface ISecondBase<T> : IEntityTask
{
Thing<T> Thing { get; }
}
Somewhere else I have a list of IBase.
This list is filled ISecondBase. I would like to be able to loop through the list of Base, but using some reflection tricks and hacks als be able to call Thing on the items. I know they're there, the compiler doesn't.
So I'd have to cast it to its concrete type at runtime, but this cast has to be dynamic, based on reflected information in the loop... So all type information is dynamic... I'm starting to think in circles :)
Since I know on beforehand that everything inside it is always of the SecondBase type, I decided to use the dynamic keyword and just let it resolve at runtime. This seems to me like an easy way out. Is there some best practice for these cases? Should I redesign, without loss of generality, and how?
foreach(var x in y)
{
dynamic melp = x;
melp.Thingy;
}
Where to start?
Edit: Perhaps some more code to make the example less contrived.
I have the base classes as mentioned. In real life they look like this:
public interface IEntityTask
{
string Name { get; }
void Run();
}
public interface IEntityTask<T> : IEntityTask
{
Task<T> Task { get; }
}
//Then there are classes that implement these:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
public T Entity { get; private set; }
public Func<T, Guid> EntityMethod { get; private set; }
public Task<Guid> Task { get; private set; }
public void Run()
{
Task = Task<Guid>.Run(() => entityAccess.CreateEntity<T>(Entity, EntityMethod));
}
}
public class ReadEntityTask<T> : IEntityTask<T>
{
public Guid EntityId { get; private set; }
public Func<Guid, T> EntityMethod { get; private set; }
public Task<T> Task { get; private set; }
public void Run()
{
Task = Task<T>.Run(() => entityAccess.ReadEntity<T>(EntityId, EntityMethod));
}
}
//Furthermore there is a class called EntityTaskManager, which holds a list of these things and runs, awaits & collects the results on them.
public class EntityTaskManager
{
public List<IEntityTask> EntityTasks { get; set; } // I want tasks of Guid and bool in here!!!!
public Dictionary<string, object> EntityTaskResults { get; set; }
}
In a calling class I construct a new EntityTask and add it to the list. And then call RunTasks on the manager.
I'd modify IEntityTask like this:
public interface IEntityTask
{
string Name { get; }
void Run();
object Result { get; }
}
If EntityTaskManager is the only place, where you work with IEntityTask type, the implementation of Result would be explicit:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
/* The rest of code here */
object IEntityTask.Result
{
get { return Task.Result; }
}
}
Then fetching task results should be trivial:
var results = entityTasksManager
.EntityTasks
.Select(t => t.Result);
I have multiple classes inheritance structure in my code. Class D inherits from class C which inherits from class B which inherits from base class A. Each of them has TryParse method.
My question is there any way to access directly the class you are deriving from, not base?
If I am correct code base.TryParse in class D will call A.TryParse.
How do I access C.TryParse or B.TryParse from class D?
I'll be more specific by describing problem I am trying to solve.
I have filenames that are composed of many things.
In general it goes like this:
GalleryName-GroupName-PictureName-Dimensions.jpg // picture itself
Example: Domestic-Animals-Dogs-Catching-a-Frisbee-800x600.jpg
GalleryName: Domestic-Animals
GroupName: Dogs
PictureName: Catching-a-Frisbee
Dimensions: 800x600
Extension: jpg
and more variations:
GalleryName-GroupName-PictureName-Dimensions.htm // related htm file
GalleryName-GroupName-PictureName-Dimensions-th.jpg // thumb - notice the -th
I will need to work with shorter parts of that complex name as well - alsmot every possible variation:
GeneralFileName.Extension
PictureName-Dimension.Extension
GroupName-PictureName-Dimensions.Extension
GalleryName-GroupName-PictureName-Dimensions.Extension
GalleryName-GroupName-PictureName-Dimensions-th.Extension
I wanted to solve it like this.
public struct PictureDimension
{
public int Width;
public int Height;
public static bool TryParse( string parseString, out PictureDimension result )
{
// get it done
}
}
class FileNameWithExtension
{
public string FileName { get; private set; }
public string Extension { get; private set; }
public bool TryParse( string parseString )
{
// extract filename from extension
}
}
class PictureDimensionExtensionName : FileNameWithExtension
{
// inhereted from FileNameWithExtension
// public string FileName { get; private set; }
// public string Extension { get; private set; }
public string PictureName { get; private set; }
public PictureDimension Dimension { get; private set; }
public new bool TryParse( string parseString )
{
base.TryParse( parseString );
// get rest of it done
}
}
}
class GroupPictureDimensionExtensionName : PictureDimensionExtensionName
{
// inhereted from PictureDimensionExtensionName
// public string FileName { get; private set; }
// public string Extension { get; private set; }
// public string PictureName { get; private set; }
// public PictureDimension Dimension { get; private set; }
public string GroupName { get; private set; }
public new bool TryParse( string parseString )
{
==> firstAboveBase.TryParse( string parseString );
// get rest of it done
}
}
class GalleryGroupPictureDimensionExtensionName :
GroupPictureDimensionExtensionName
{
public string GalleryName { get; private set; }
public new bool TryParse( string parseString )
{
==> secondAboveBase.TryParse( string parseString );
// get rest of it done
}
}
I am not aware of any keywords like firstAboveBase and secondAboveBase. Is there any way to access directly the class you are deriving from, not base?
You're using new. Don't do that. That gets rid of polymorphism entirely, which surely isn't what you're intending. Shadowing members makes code much harder to follow, in my experience - why are you doing it?
However, if you call base.Foo from class D which derives from class C and which exposes a Foo method, it will call C.Foo.
Sample code:
using System;
class A
{
public virtual string Foo() { return "A"; }
}
class B : A
{
public override string Foo() { return "B"; }
}
class C : B
{
public override string Foo() { return "C"; }
}
class D : C
{
public override string Foo() { return "D"; }
public void ShowBaseFoo()
{
Console.WriteLine("base.Foo() from D: {0}", base.Foo());
}
}
class Test
{
static void Main()
{
new D().ShowBaseFoo();
}
}
Output:
base.Foo() from D: C
directly the class you are deriving from, not base?
base already designates the immediate class you are deriving from.
Otherwise base would always mean System.Object (the mother of all classes).
In your specific case, you can, since you aren't overriding them.
((FileNameWithExtension)this).TryParse(...);
However, it is impossible to call a grandparent version of an overridden method.
Is it possible to just do a cast to the parent type you need?
D myVar = New D();
((B)myVar).TryParse(...)
I'm beginning to fall in love with Extension Methods, but I just don't know how to create an EM only for a determinate Object type.
I have for example:
public static void AddPhoneNumberToContact(this Contact contact, PhoneType type, String number)
{
lock (contact)
{
PhoneRow pr = PhoneRow.CreateNew();
pr.SetDefaults();
pr.PtypeIdx = type;
pr.PhoneNumber = number;
contact.Phones.Add(pr);
pr = null;
}
}
My problem is that I want to also Have this method in the Person object, and that is why I named
AddPhoneNumberToContact
AddPhoneNumberToPerson
Is there a way to have AddPhoneNumber and deal with the object that is provided?
or the solution is to have
public static void AddPhoneNumber(this object contact, ...
{
...
if(typeof(Contact) == contact)
((Contact)contact).Phones.Add(pr);
else if(typeof(Person) == contact)
((Person)contact).Phones.Add(pr);
}
Thank you.
How about writing two extension methods:
public static void AddPhoneNumber(this Contact contact, PhoneType type);
and
public static void AddPhoneNumber(this Person person, PhoneType type);
Looks cleaner to me.
If there's some common code between the two, extract that into a separate method.
Make Contact and Person implement common interface - say IContactWithPhoneNumbers - and then write an extension method "for this interface".
public interface IContactWithPhoneNumbers {}
public class Contact : IContactWithPhoneNumbers {}
public class Person : IContactWithPhoneNumbers {}
public static void AddPhoneNumber(this IContactWithPhoneNumbers obj) {}
Reading your comments (objects are from an SDK and are not editable). I would probably do something like this:
public class Util
{
//common util method
public static void AddPhoneNumber(object obj, string phoneNumber)
{
if(obj is Contact)
((Contact)contact).Phones.Add(phoneNumber);
else if(obj is Person)
((Person)contact).Phones.Add(phoneNumber);
}
//extension method for Person
public static void AddPhoneNumber(this Person p, string phoneNumber)
{
AddPhoneNumber((object)p, phoneNumber);
}
//extension method for Contact
public static void AddPhoneNumber(this Contact c, string phoneNumber)
{
AddPhoneNumber((object)c, phoneNumber);
}
}
I do think the best practice though when you have control of the underlying objects would be to implement a common interface.
You might make your extension method generic, e.g.:
public static void AddPhoneNumberToContact<T>(
this T contact,
PhoneType type,
String number
)
{
PhoneRow pr = PhoneRow.CreateNew();
pr.SetDefaults();
pr.PtypeIdx = type;
pr.PhoneNumber = number;
((T)contact).Phones.Add(pr);
pr = null;
}
You won't be able to use lock because "'T' is not a reference type as required by the lock statement", so you might have to return some value.
If it complains about not being able to resolve the Phones method on type T, you could:
Pass in some function delegate that would take type T, return nothing, and perform the action ((T)contact).Phones.Add(pr);.
Or you could create an interface like the following:
public interface IPhoneable
{
IList<Phone> Phones();
}
Then, once you have that interface, you can add the following to your generic extension method:
public static void AddPhoneNumberToContact<T>(
this T contact,
PhoneType type,
String number
) where T : IPhoneable {...}
Here, T is still a generic type, but now your AddPhoneNumberToContact method has the requirement that, whatever T is, it inherits from the IPhoneable interface, which you just defined to have the Phones() method.
See also C# Extension Method for Generic Collections.
If you can not change Person and Contact you can create a subclass of them and let them implement the common interface.
In the extension method you declare the common interface as parameter:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var p = new MyPerson();
p.Name = "test";
p.AddPhonenumber("555-2356");
Console.WriteLine(string.Join(", ", p.Phonenumber));
var c = new MyContact();
c.Name = "contact";
c.AddPhonenumber("222-235");
Console.WriteLine(string.Join(", ", c.Phonenumber));
}
}
public class Contact
{
public Contact() {
this.Phonenumber = new List<string>();
}
public string Name { get; set; }
public List<string> Phonenumber { get; set; }
public string Foo { get; set; }
}
public class Person
{
public Person() {
this.Phonenumber = new List<string>();
}
public string Name { get; set; }
public List<string> Phonenumber { get; set; }
public string Bar { get; set; }
}
public class MyContact: Contact, IType {
}
public class MyPerson: Person, IType {
}
public static class Extensions {
public static void AddPhonenumber(this IType type, string number){
type.Phonenumber.Add(number);
}
}
public interface IType {
string Name {get; set; }
List<string> Phonenumber {get; set;}
}