Implementing interface C# - c#

I'm not new to C#, but I have found a behavior that is a little puzzling.
I have an interface
public interface IApplicationPage
{
Person ThePerson { get; set; }
Application Application { get; set; }
}
I implement the interface on a page
public partial class tripapplication2 : System.Web.UI.Page, IApplicationPage
{
Person IApplicationPage.ThePerson { get; set; }
Application IApplicationPage.IApplicationPage.Application { get; set; }
}
However, when I attempt to reference ThePerson in the page itself I need to jump through hoops. For example.
1) ThePerson.Birthday
Gives an error saying "The name 'ThePerson' does not exist in the current context."
2) ((IMissionTripApplicationPage)this).ThePerson.Birthday
This works, but it looks awful.
Is there a better way to reference the implemented properties?

It looks like you left a line out in your sample. I believe the ThePerson line in the implementation should read
Person IApplicationPage.ThePerson { get; set; }
This type of implementation is known as an explicit interface implementation. This means the member will only be viewable when the object is seen through a reference of the interface type.
If you want the member to be viewable through a concrete type reference, make it public and remove the explicit implementation
public Person ThePerson { get; set; }

Implement them as public properties:
public partial class tripapplication2 : System.Web.UI.Page, IApplicationPage
{
public Person ThePerson { get; set; }
public Application IApplicationPage.Application { get; set; }
}
Edit
Question now edited to show these were implemented originally as explicit. So, I should restate mine as implement them as public rather than explicit implementations of the properties.

Related

Detect nested type of generic

I'm working on a project which needs to determine the type of an object, take the information from that type and move it to a structure that fits in our database.
For this, I'm using Pattern Matching with a case statement which works fine.
The only thing that I got stuck with is that some types have nested types as well. The information in those nested types is the information that I need.
Take a look at the code below:
public class CallAnswered
{
public string Caller { get; set; }
public MetaDataInformation MetaData{ get; set; }
}
public class CallAbandoned
{
public string ReasonForAbandonment{ get; set; }
public MetaDataInformation MetaData { get; set; }
}
public class MetaDataInformation
{
public DateTime ReceivedAt { get; set; }
public DateTime AnsweredAt { get; set; }
}
public void DetermineType<T>(T callEvent)
{
switch (callEvent)
{
case CallAnswered callAnswered:
case CallAbandoned callAbandoned:
// Somehow, I need to access the "MetaData" property as a type
break;
}
}
Like shown in the code above, I am able to detect the parent type and assign it a variable. Bu I have no clue on how to get the nested MetaDataInformation type.
Does anyone have an idea how this can be resolved?
You do not need a generic type here. By deriving from an abstract base class, you can solve two problems.
You can use the base type instead of the generic type and access all the public members of this base class.
You can add an abstract method in the base class implemented in the two derived classes making the switch statement obsolete.
public abstract class Call
{
public MetaDataInformation MetaData { get; set; }
public abstract void Process();
}
public class CallAnswered : Call
{
public string Caller { get; set; }
public override void Process()
{
// TODO: Do Answer things. You can access MetaData here.
}
}
public class CallAbandoned : Call
{
public string ReasonForAbandonment{ get; set; }
public override void Process()
{
// TODO: Do Abandonment things. You can access MetaData here.
}
}
somewhere else
public void ProcessCalls(Call callEvent)
{
// Replaces switch statement and does the right thing for both types of calls:
callEvent.Process();
}
This is called a polymorphic behavior.
See also:
Polymorphism (Wikikpedia)
Polymorphism (Microsoft Docs)

Auto-generated class from EF6 to implement custom interface

I am using EF 6. I have a table in db for which the auto-generated class looks like this:
public partial class tblPreparation
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblPreparation()
{
this.tblPreparationItem = new HashSet<tblPreparationItem>();
}
public int id { get; set; }
public string name { get; set; }
public System.DateTime date { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tblPreparationItem> tblPreparationItem { get; set; }
}
In my code, I want this class to extend another class EntityObject, which is in the namespace System.Data.Entity.Core.Objects.DataClasses (and implement another interface). So I created wrote this partial class:
public partial class tblPreparation : EntityObject, IMyInterface
{
}
It doesn't throw a syntax error but when I run the application I get runtime error: "The type 'tblPreparation' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive or generic, and does not inherit from EntityObject." What am I missing?
I assum it's because they are not in the same namespace. Is there a way to fix this?
I may have misunderstood your comment on the namespace, but for clarity, a Partial class is only actually a partial class when it is in the same namespace of the corresponding partial class, otherwise what you have are just two separate single classes with the same name claiming to be partial. If this is the case, the fix is simple. Put them in same namespace.
However, it is more likely due to adding the EntityObject to the class hierarchy, as oerkelens mentioned. EF 6 creates proxies of your POCOs, for this reason your classes must have parameterless constructors. Adding another class may prevent the db context from creating proxies of your objects.
Remove just that class from the hierarchy, check whether you can materialise these entities to verify or rule it out.
Edit - No, it definitely is due to EntityObject.
I reproduced this by first having my entity implement some interface in a partial class. That worked great. Then I had partial class inherit from EntityObject that failed with your error.
After reproducing this error, I created a class called MyStupidClass and replaced EntityObject with MyStupidClass and I could still materialise entities (even with the top level properties of EntityObject).
So it depends on the class you introduced to the hierarchy.
class Program
{
static void Main(string[] args)
{
using (var db = new schedulerEntities())
{
var schedules = db.Schedules.ToArray();
foreach (var schedule in schedules)
{
Console.WriteLine($"{schedule.Cron} - {schedule.FriendlyDescription}");
}
}
Console.ReadLine();
}
}
public partial class Schedule: MyStupidClass, IScheduler
{
public string FirstName { get; set; }
}
public class MyStupidClass
{
public EntityKey EntityKey { get; set; }
public EntityState State { get; set; }
}
interface IScheduler
{
long Id { get; set; }
string Name { get; set; }
string Cron { get; set; }
}

C# Interface containing an array of interface, hierarchy

I have an Interface for a master-detail common interface hierarchy:
public interface ITModel
{
ITPeriodHead[] PeriodHeads { get; set; }
}
I try to use it this way:
public class T19Model:ITModel
{
public T19Item[] Items { get; set; }
**public T19PeriodHead[] PeriodHeads { get; set; }**
}
The array of PeriodHeads causes error at compile time,
despite T19PeriodHead implements ITPeriodHead, like this:
public class T19PeriodHead : BaseTPeriodHead, ITPeriodHead
{ ...
What is the solution? If I use the array of ITPeriodHead, I will not be able to access the periodhead items members, properties, methods....
Any help is appriciated.
You have to honor the interface contract. You are returning a more specific class that the interface defines, so you are not fully defining the interface.
You could explicitly implement the interface, but you have an issue with the setter - what if someone tries to set the property to an array of objects that are not T19PeriodHeads?:
public class T19Model:ITModel
{
public T19Item[] Items { get; set; }
public T19PeriodHead[] PeriodHeads { get; set; }
ITPeriodHead[] ITModel.PeriodHeads
{
get {return PeriodHeads;}
set {/* what to do here if value is not an array of T19PeriodHeads? */}
}
}
If you do not need a setter for the array property (maybe an Add method instead?) then you are fine.

Interface inheritance and the new keyword

I want:
public interface IBase
{
MyObject Property1 { get; set; }
}
public interface IBaseSub<T> : IBase
{
new T Property1 { get; set; }
}
public class MyClass : IBaseSub<YourObject>
{
public YourObject Property1 { get; set; }
}
But this doesn't compile. It gives the error:
//This class must implement the interface member IBase.Property1
Can anyone shed some light on this? I thought it should work..
Thanks
IBaseSub<T> requires IBase. I say "requires" because it more accurately reflects the practical implications than to say it "inherits" IBase, which implies overriding and other things that simply don't happen with interfaces. A class which implements IBaseSub<T> can actually be said to implement both, like so:
public class MyClass : IBase, IBaseSub<YourObject>
Going back to what I said about inheritance - there is no such thing with interfaces, which means just because both interfaces have a property with the same name, the derived one isn't overriding or hiding the base one. It means that your class must now literally implement two properties with the same name to fulfill both contracts. You can do this with explicit implementation:
public class MyClass : IBase, IBaseSub<YourObject>
{
public YourObject Property1 { get; set; }
MyObject IBase.Property1 { get; set; }
}
You need to implement the properties from both IBase and IBaseSub<YourObject>, since the latter expands on the former.
Using new in IBaseSub<T> does not let you "off the hook" regarding the necessity to have a MyObject Property1 { get; set; }. It simply allows you to declare another property named Property1 that implementors of IBaseSub<T> must have.
Since you cannot have two properties with the same name in MyClass, you will be forced to implement at least one of them explicitly:
public class MyClass : IBaseSub<YourObject>
{
MyObject IBase.Property1 { get; set; }
public YourObject Property1 { get; set; }
}

Self-referential generic class templates

Is it possible to build the following heterogeneous (generic) linked list data type?
class MyClass<TPrev, TNext>
where TNext : MyClass<TPrev2, TNext2>
where TPrev2 : MyClass<TPrev, TNext>
edit: Notice in particular the new type TNext2 which is not defined.
edit2: ... which makes the above snippet non-functional as written.
No, you can't model what you want. You could do this:
class Link<TPrev, TValue, TNext>
{
public TPrev Prev { get; set; }
public TValue Value { get; set; }
public TNext Next { get; set; }
}
But you can't do:
class Link<???, TValue, ???>
{
public Link<???> Prev { get; set; }
public TValue Value { get; set; }
public Link<???> Next { get; set; }
}
The problem is that if you declare that the previous and next elements of your list must also be lists of some generic type, then you've attempted to define a type of infinite size. There's no way to say, "There is no next node after this" because the next node must be a Link<T> for some other link type and you run into an infinite regress.
No, this is not possible because you haven't defined TNext2 or TPrev2 as part of the class definition. You can't have a generic parameter like that unless its an existing type, or is a generic type parameter in the class definition.
But then, if TPrev2 is an existing type, you can't specify a constraint on it like you are trying to do.
Take a look at this blog entry for an interesting idea on the topic. In essence you could do something like this:
public abstract class LinkedListBase<T>
where T : LinkedListBase<T>
{
public T Next { get; set; }
public T Previous { get; set; }
}
public class LinkedListImpl : LinkedListBase<LinkedListImpl>
{
public string Name { get; set; }
// all of the value properties go here...
}
So essentially the value itself contains the links to the previous and next.

Categories

Resources