C# Get value of a property from an object hidden behind Interface - c#

To explain it better, I have an object that has property of interface type that can be carrying a variety of different objects.
public class RequestParameters {
public IRequest Request { get; set; }
}
Say the interface looks something like this:
public interface IRequest {
string Username { get; set; }
string Password { get; set; }
}
Now upon receiving the RequestParameters object, I want to get the value of a property PersonId from the object inside Request property. The interface doesn't and shouldn't contain this property, as not all of the Request types have that property. And I don't know which of the dozens of types will the Request object correspond to, so casting isn't a solution.
So how can I possibly fetch the property PersonId in such a case? I suppose some sort of reflection is the only way, but how exactly can it be done?

What about creating an intermediate interface?
public class RequestParameters
{
public IRequest Request { get; set; }
}
public interface IRequest {
string Username { get; set; }
string Password { get; set; }
}
public interface IRequestWithId : IRequest
{
string ID {get; set; }
}
Now you can check against that interface instead of a concrete class to check if there is an ID or not.
Other than that there is only reflection which is a really bad idea here. When defining interfaces you want to reduce code-coupling which means you donĀ“t want to rely on actual types (that define how things are done) but only their behaviour (what can be done with them). Using reflection would circumvent this as you indirectly rely on the actual types. Furthermore using reflection is bad for maintainance, in particular when you refactor the methods (renaming for example).

first of all, in c# there is another type called abstract class which in my opinion would be a better suit for your situation. take a look at this question. interfaces are not meant to hold variables, only functions.
public abstract class ARequest
{
string Username { get; set; }
string Password { get; set; }
public abstract int GetId() {}
}

Related

C# DTO with calculated property

I have some DTOs that need save to the redis, and I want all of them have a property or method to generate key of redis.
public class Product
{
public string Name {get; set;}
public string Type {get; set;}
// Use Property (Maybe Inherit a base class or interface)
public string CacheKey
{
get
{
return Type + "_" + Name;
}
}
// User Method (Maybe Inherit a base class or interface)
public string GetCacheKey()
{
return Type + "_" + Name;
}
}
Or... I should not add them to DTO, but I want all the DTOs that need save to redis were must have a key, and each of Key were generate by the property of itself.
Can someone give me some suggestion?
We have to think pragmatic here. The implementation of a cache key getter function is not real business logic in this case.
My suggestion is, create an interface and implement it in any DTO that needs it with the cache key getter function.
An absolut valid approach int terms of pragmatic.
Observing the Open-Closed Principle of the SOLID principles
You should not change the established purpose of a DTO (As #GlennvanAcker said a DTO does not have logic).
However, we can give it an extension method... Which is what I suggest.
public static class ProductExtensions
{
public static string CacheKey(this Product product)
{
return product.Type + "_" + product.Name;
}
}
#HansKesting pointed out that I didn't show how to make this work for classes other than Product...
This would require us to extend the base class or interface. If this method is to be applied to multiple classes; the compiler needs to know that the class has the required properties(Type and Name):
e.g.
// I'm not calling this interface IDto because I am not assuming that all DTOs have these properties.
public interface IDtoWithTypeAndName
{
public string Type { get; set; }
public string Name { get; set; }
}
public static class DtoExtensions
{
public static string CacheKey(this IDtoWithTypeAndName dto)
{
return dto.Type + "_" + dto.Name;
}
}
public class Product : IDtoWithTypeAndName
{
public string Type { get; set; }
public string Name { get; set; }
}

use MVC like validation in WPF

I'm using MVC with entity framework for a while.
and now i need to make a wpf application and I'm looking for a way to validate like the model-state in WPF
This is how my class looks
public class Customer
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(100)]
public string Address { get; set; }
[MaxLength(20)]
public string PhoneNumber { get; set; }
[EmailAddress]
public string Email { get; set; }
public List<Order> Orders { get; set; }
}
Is there any easy way for me to check if its valid?
what I'm really trying to avoid is to have to write all the validation rules
Unfortunately no, I had to create a interface called IValidateable which extends INotifyDataErrorInfo where I define a method Validate that I can pass the property name to or leave it blank to validate the entire object.
The INotifyDataErrorInfo is an .Net interface that allows the validation to be asynchronous and has already a property HasErrors to check the object after it has been validated.
I then implemented all of the required methods in a base class, when I need to validate the entire object, this base class uses reflection to list the properties and then validate each one.
In the base class I have an virtual method like so:
protected virtual void PerformValidation (String Property) {}
My models override this method and do the specific validation required. This method is not required to be override and as I said, you can add support to attributes in the base class.
You can extend the IDataErrorInfo instead of the INotifyDataErrorInfo if you don't need asynchronous validation.
Then I can just do something like this:
SomeModel.Validate ();
if (SomeModel.HasErrors)
Do Something...
Or:
if (!SomeModel.Validate ())
Do Something...

C# (Web API) Multilayer (IOC) API Controller Return Type

I am building an ASP Web API application and this time I thought I will go with the MVC pattern. I got along with most of the stuff, but there is one thing of which I am unsure. First of all my project consists of the following:
Data Layer
Business Layer
Model Layer (just the model with the properties)
Service Application (here are my controllers)
every one of them in a separate project
Lets say I have the following controller
public class TestController : ApiController
{
ISomeService _someBusiness;
public TestController(ISomeService someBusiness)
{
_someBusiness = someBusiness;
}
public **SomeModelObject** GetModelObject(ind id)
{
return _someBusiness .GetSomeModelObject(id);
}
}
Now my problem is the return value of GetModelObject(int id). Here it says SomeModelObject. That implies that my Service application (or my controller) has to know everything about the model which is being used (so I dont see the point in defining it in a separate .dll). One way would be to define the model (precisely the get/set mothods) as an interface, but I think that it would be too much that every model class has an interface (mostly because, as I said, just the properties are being stored inside the model), and despite that I just does not feel right to build an interface for a class which only stores data. So, is there any generic response type which is being used in this case (even some completely different approach), or do I have to use my model classes (or may i just always use string and it is being converted to the appropriate format by the client) ?
There's a good reason to use an interface to hide the complexity of the model object. It holds data, sure. But it holds unnecessary data that is only meaningful to the data layer. Take this EF model:
public class Employee
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string Name { get; set; }
public virtual Collection<TimeCard> TimeCards { get; set; }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
}
This is a fairy common EF model. It contains a surrogate key Id, and a foreign key DepartmentId. Those values are meaningless except for the database and, by extension, for entity framework. EmployeeNumber is the natural key which uniquely identifies the entity in the user's domain.
Outside of database access, you should really only deal with natural data values. You could do this by declaring yet another data-carrying class in the Business layer and perform mapping, or a better idea is to use an interface to hide all of the members that are not useful.
public interface IEmployee
{
string EmployeeNumber { get; }
string Name { get; set; }
ICollection<ITimeCard> TimeCards { get; }
IDepartment Department { get; set; }
}
Notice the lack of some setters in the interface. You'll never want to change the EmployeeNumber because that is the natural key for the entity. Likewise, you'll never assign a collection object to the TimeCards property. You'll only ever iterate over, add, or remove them.
Now your Employee class becomes
public class Employee : IEmployee
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string Name { get; set; }
public virtual Collection<TimeCard> TimeCards { get; set; }
ICollection<ITimeCard> IEmployee.TimeCards { get { return TimeCards; } }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
IDepartment IEmployee.Department { get { return Department; } set { Department = value; } }
}
In your business layer and above, you'll only use variable of IEmployee, IDepartment, and ITimeCard. So you are exposing a tighter API to the higher layers, which is a good thing.
You could try to use a generic approach at controller level:
public class BusinessController<T> : ApiController
{
ISomeService _someBusiness;
public TestController(ISomeService someBusiness)
{
_someBusiness = someBusiness;
}
public T GetModelObject(ind id)
{
return _someBusiness.GetSomeModelObject(id);
}
}
Finally your controlers inherit from BusinessController instead of ApiController:
public class TestController : BusinessController<SomeModelObject>
{
}
You could also take advance of the templating to inject the right "ISomeService" by using an IoC container and a bootstrapper.

Cannot access nested classes or members of base class

I'm having some weird problems here with a Class that I've written. I cannot access anything inside of Account, unless I access it directly from Account.Whatever.
I'd like to be able to do:
Account account = new Account();
account.Name...
but I can't. Nothing shows up in intellisense. I can only access things if I do:
Account. - for example, Account.AccountHolder...
class Account
{
class AccountHolder
{
enum Salutation
{
Mr,
Mrs,
Ms,
Miss,
Dr,
Hon
}
struct Name
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
enum Sex
{
Male,
Female
}
}
}
I don't understand what's going on. Note, that I have also tried every possible combination of things but something is very wrong here. I've tried adding public to my Account class. I've tried adding public to my AccountHolder class. I've tried using public static etc etc etc.
I've never had this problem before. And why am I experiencing this same problem no matter how much I change it around?
The Account class is in an Account.cs file inside the same winforms project.
One real question might be: Why do you need Nested Types here at all?
Nested types are especially used when no other types cannot reuse a type of your parent type, that is, if your nested type shall expose properties or values only applicable to your parent type. Otherwise it is mostly best to create independant types.
To me, it looks reasonable to think that you might use the Salutation enumeration outside of the AccountHolder class, as an Account Holder is nothing more than a legal entity, that is, a real person or a company.
If your system could use Salutation elsewhere, than it is best to create the enumeration per itself, in its own file, and expose a property out of your AccountHolder class.
Salutation
public enum Salutation {
Mr
, Mrs
, Ms
, Miss
, Dr
, Hon
}
AccountHolder
public class AccountHolder {
public Salutation Salutation { get; set; }
// ...
}
In the later, one might also be insterested to know what's an account holder at once?
Might it be a company, a person, a customer, a supplier, or else?
Then perhaps shall you consider to define a hierarchy of account holders and make it a property of the most general class type.
LegalEntity
public class LegalEntity {
public string Name { get; set; }
}
Company
public class Company : LegalEntity {
// Some members specific to a Company here...
}
Person
public class Person : LegalEntity {
public Salutation Salutation { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get { return base.Name; } set { base.Name = value; } }
// Some other members specific to a person here...
}
Then, you have your Account class
public class Account {
public LegalEntity AccountHolder { get; set; }
}
So my point is that there is no use of Nested Types here, depending on your needs, which I'm not actually aware, obviously. And it turns out that an AccountHolder may now be of any types deriving from LegalEntity. Later on, when there is a need for another type of AccountHolder, you may simply derive from LegalEntity, or any other types which actually derives from it to make it an AccountHolder, as an AccountHolder is simply a property of an Account, and not a class per itself.
Some examples of using Nested Types adequately:
Why Would I Ever Need to Use C# Nested Classes
Why/when should you use nested classes in .net? Or shouldn't you?
Furthermore, you will need to make your Nested Types public in order to access them from outside of your class. This doesn't mean that will be able to avoid the Parent.NestedType nomenclature, you will not.
Apart from it, I see no problem in your code. Nested Types are by definition hidden somehow within another type. So when you wish to access them, you always need to type in the parent name which contains the type you need to access.
Plus, once you can access the Nested Type, you will be obliged to create members into your Account class to holde references to your instances of those Nested Types. IMHO, there is no gain of using them here. But hey, I insist, I'm not aware of your reality and the choices behind your design.
You are trying to access nested class, struct, enum. It should be done with the nesting class name, e.g. Account.Name.
But if you have
class Account
{
public struct Name
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public Name MyName {get; set;}
}
then you may access the MyName property using the instance of Account class.
This is how the language works.
What you are probably wanting to use here are namespaces. Any nested class will always have to be fully qualified with its parent classes to be used. If you use a namespace, anything within that namespace can be used together without fully-qualifying, and can be used outside the namespace (within the bounds of access modifiers) by either fully-qualifying or by inserting a using directive (using Accounting; in this case).
Also, are you sure you want to be using a struct? Value types are immutable, so if you change any member of that struct, you're always creating an entirely new instance of the struct (generally significantly less efficient).
namespace Accounting
{
class Account
{
public PersonName Name { get; set; }
public Sexes Sex { get; set; }
public Salutations Salutation { get; set; }
}
class PersonName
{
public string First { get;set; }
public string Middle { get; set; }
public string Last { get; set; }
}
enum Salutations : byte
{
Mr,
Mrs,
Ms,
Miss,
Dr,
Hon
}
enum Sexes : byte
{
Male,
Female
}
}

C# - WCF - Generics - [KnownType(typeof(xxx))]

My client has 10 tables that it needs to load via an internal WCF to a server. Since all this is internal, I can write both client and server using whatever technique i want.
On the Client, I thought to use LINQ to load data from the tables to a List, List and so on...
On the Server, I thought to have a [DataContract] as follow:
[DataContract]
[KnownType(typeof(Table1))]
[KnownType(typeof(Table2))]
[KnownType(typeof(Table3))]
public class GenericType<T>
{
[DataMember]
public List<T> Data { get; set; }
}
and then add the classes that will represent the matching Tables on the Client.
[DataContract]
public class Table1
{
[DataMember]
public int UserID { get; set; }
[DataMember]
public string FullName { get; set; }
}
[DataContract]
public class Table2
{
[DataMember]
public int UserID { get; set; }
[DataMember]
public string Address1 { get; set; }
}
[DataContract]
public class Table3
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}
When I create the client reference, i'm NOT getting all the classes declared on the server and it seems that ONLY the 1st [KnownType] specified on the [DataContract] becomes visible to the Client.
I was under the impression that Generics was meant to allow multiple types but am I right to think that WCF can only handle one [KnownType] x class ??
And if so, my only way to code this would be to copy and paste 10 times the GenericType class and on each copy, change the [KnownType] ??
Cause if that's the only solution, then what are the real benefits to use Generic instead of straight defined List, List for my params ??
Any thought will help clarify my mind here
The problem happens because unless ONE of the WCF methods uses any of the CLASSES declared as [DataContract] ...it seems that WCF does NOT brings those classes to the Client.
Is this the expected case?
You could try attributing your interface method with the ServiceKnownType attribute for each of the classes.
There is another option, which is to implement the generic lists in classes that are attributed with CollectionDataContract:
[CollectionDataContract]
public class Table1Collection
Inherits List<Table1>
On the client side, you can the edit Reference.svcmap and enumerate each of the collections in the CollectionMappings section:
<CollectionMappings>
<CollectionMapping TypeName="My.Namespace.Table1Collection" Category="List" />
This allows you to reuse the same code on both ends of the pipe.

Categories

Resources