Referencing to my previous question, the story begins in that fact that I have a bunch of svcutil-generated classes. They are generated from external WSDL. Here you go:
First request class:
public partial class getcarsRequest
{
[System.ServiceModel.MessageHeaderAttribute(Namespace = "http://svc.datadomains.com/revision123_2/")]
public CarsServiceApp.RequestHeader Header;
[System.ServiceModel.MessageBodyMemberAttribute(Name = "getcarsRequest", Namespace = "carinfo", Order = 0)]
public CarsServiceApp.getcars MessageWrap;
public getcarsRequest()
{
}
public getcarsRequest(CarsServiceApp.RequestHeader Header, CarsServiceApp.getcars getcarsRequest1)
{
this.Header = Header;
this.MessageWrap = getcarsRequest1;
}
}
public partial class getcars
{
private MessageType messageField;
private MessageDataGetcarsRequest messageDataField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public MessageType Message
{
get
{
return this.messageField;
}
set
{
this.messageField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public MessageDataGetcarsRequest MessageData
{
get
{
return this.messageDataField;
}
set
{
this.messageDataField = value;
}
}
}
public partial class MessageDataGetcarsRequest
{
private AppDataGetcarsRequest appDataField;
private AppDocumentType appDocumentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public AppDataGetcarsRequest AppData
{
get
{
return this.appDataField;
}
set
{
this.appDataField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public AppDocumentType AppDocument
{
get
{
return this.appDocumentField;
}
set
{
this.appDocumentField = value;
}
}
}
public partial class AppDataGetcarsRequest
{
private string addressField;
private int codeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public address address
{
get
{
return this.addressField;
}
set
{
this.addressField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public int code
{
get
{
return this.codeField;
}
set
{
this.codeField = value;
}
}
}
Second:
public partial class getdriversRequest
{
[System.ServiceModel.MessageHeaderAttribute(Namespace = "http://svc.datadomains.com/revision123_2/")]
public carsServiceApp.RequestHeader Header;
[System.ServiceModel.MessageBodyMemberAttribute(Name = "getdriversRequest", Namespace = "driverinfo", Order = 0)]
public carsServiceApp.getdrivers MessageWrap;
public getdriversRequest()
{
}
public getdriversRequest(carsServiceApp.RequestHeader Header, carsServiceApp.getdrivers getdriversRequest1)
{
this.Header = Header;
this.MessageWrap = getdriversRequest1;
}
}
public partial class getdrivers
{
private MessageType messageField;
private MessageDataGetdriversRequest messageDataField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public MessageType Message
{
get
{
return this.messageField;
}
set
{
this.messageField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public MessageDataGetdriversRequest MessageData
{
get
{
return this.messageDataField;
}
set
{
this.messageDataField = value;
}
}
}
public partial class MessageDataGetdriversRequest
{
private AppDataGetdriversRequest appDataField;
private AppDocumentType appDocumentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public AppDataGetdriversRequest AppData
{
get
{
return this.appDataField;
}
set
{
this.appDataField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public AppDocumentType AppDocument
{
get
{
return this.appDocumentField;
}
set
{
this.appDocumentField = value;
}
}
}
public partial class AppDataGetdriversRequest
{
private string nameField;
private int customerCodeField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 0)]
public name name
{
get
{
return this.nameField;
}
set
{
this.nameField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order = 1)]
public int customerCode
{
get
{
return this.customerCodeField;
}
set
{
this.customerCodeField = value;
}
}
}
This is just two entity generated by svcutil. There are another entities that like this two differs only by most underlying AppData property. I wrote a power shell script that preparing raw generated file renaming some fields but this is not enough to get all work done.
How can I compose classes unity? It seems like I should use parametrized interface...
I need united classes structure to devise common useful functions like checking that request is correct or create request from scratch.
Thanks in advance, guys! My brains are boiled about that stuff.
QUESTION EDIT #1
Ok, guys, here is that I would like to have. Let say we want to check any service method's request for correctness. If some request's AppData property isn't null we should consider that request as correct. Actually it would be better for us to have some common class' method for such checking. But how can we make that method if any request class has different AppData property types?
Let take a look at two generated classes and draw some imaginary path to each AppData properties.
For first class, getcarsRequest we have (in parentheses we has appropriate class type):
request (getcarsRequest) -> MessageWrap (getcars) -> MessageData
(MessageDataGetcarsRequest) -> AppData (AppDataGetcarsRequest)
For the second we have next path:
request (getdriversRequest) -> MessageWrap (getdrivers) -> MessageData
(MessageDataGetdriversRequest) -> AppData (AppDataGetdriversRequest)
So how can we redevise and reduce them to some generic interface? If we have an appropriate, common interface for that two classes we could write some CheckRequest(IRequest<T> request).
I hope I get some clarity here. Any advices/sentences will be very appreciated. If you have any questions for me please feel free to bring them to me.
As I understand it, you have two class structures that are effectively duplicated: car and driver. Instead of modifying the generated classes, you should focus on restructuring your input wsdl (which we havent seen yet).
In order to remove this duplication, consider making two Objects: car and driver and restructuring the wsdl operations in such a way that they can operate on either type of Object. In Object Oriented terms, both car and driver should inherit from the same base class that will have abstract methods that can be called by the wsdl operations. These abstract methods would then need to be implemented in the car and driver derived/concrete classes.
If you cannot edit your WSDL to provide a common type, I see two possibilities:
You could create generic wrapper classes that are parametrized with the known type. The classes would mimic the structure of the concrete classes (generated by svcutil) including their hierarchy. Then you wrap the raw object in the appropritate wrapper and use the wrapper from that point on.
Advantage: interaction with the wrapper classes are similar to the original (raw) objects without much runtime overhead.
Disadvantage: You need to create and maintain the class layout/hierarchy of the original (raw) objects as the WSDL changes.
Alternatively, you can use reflection to call the appropriate methods on the objects -- you will need to calculate the method names based on the concrete type (e.g. callFunction(o, "get", "car") to call ((GetCarsRequest)o).getCars()).
Advantage: you do not need to create and maintain a shadow type hierarchy to match the original type layout/hierarchy.
Disadvantage: reflection in general is much slower than achieving the same result via compiled bytecode.
Both of these approaches require you to know for sure at all times which type of object you are dealing with, which should not be an issue as that is the case already in your current setup.
Refactoring might be the best option, but if it isn't feasible, you can take advantage of the fact that they're partial and add an interface.
public IData<TRequest> {
T AppData { get; set; }
bool IsValid { get; }
}
public partial class MessageDataGetdriversRequest : IData<AppDataGetcarsRequest>
{
bool IsValid { get { this.AppData != null; } }
}
public partial class MessageDataGetdriversRequest: IData<AppDataGetdriversRequest>
{
bool IsValid { get { this.AppData != null; } }
}
Then you can do var data = getcars.MessageData; or var data = getdrivers.MessageData;, and then check data.IsValid.
It's also possible to implement IsValid as an extension method on this IData<T> instead of a property of IData, in which case you wouldn't even need to declare it for each class (but it would be a method, not a property).
public partial class MessageDataGetdriversRequest : IData<AppDataGetcarsRequest> { }
public partial class MessageDataGetdriversRequest: IData<AppDataGetdriversRequest> { }
public static bool IsValid(this IData<T> data)
{
return data.AppData != null;
}
Related
I have this class called BluetoothDeviceInfo from 32feet library to handle, obviously, Bluetooth related stuff.
I have created my program and it worked. However, I need to add some information to a "more complete", lets say, class which also carries GPS information.
So what I did was to created a new class MyDeviceInfo and derive it from BluetoothDeviceInfo as the code below.
Base* (which I don't have control on)
namespace InTheHand.Net.Sockets
{
public class BluetoothDeviceInfo : IComparable
{
public BluetoothDeviceInfo(BluetoothAddress address);
public bool Authenticated { get; }
public ClassOfDevice ClassOfDevice { get; }
public bool Connected { get; }
public BluetoothAddress DeviceAddress { get; }
public string DeviceName { get; set; }
.
.
.
Derive*
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
public MyDeviceInfo(BluetoothAddress address) : base(address)
{
gpsSignal = false;
}
#region Properties
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
And I substituted all my BluetoothDeviceInfo types in my code with MyDeviceInfo types.
Everything seems working except this part.
This particular method called Client.DiscoverDevice() returns a list of Bluetooth devices available in the type BluetoothDeviceInfo. And since this is of a type base class, it doesn't make sense that I would cast it to a variable of my derive class MyDeviceInfo and I can't get past this point since I need the list of devices. Even though sounding wrong I tried to cast it using this code (which obviously didn't work)
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (IEnumerable<MyDeviceInfo>)cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...
Since this logic doesn't fit into inheritance I thought of composition. However, this isn't quite fit the composition line of thought such as object Bird can have flying functionality of type Airplane but not the whole lot cuz I actually need my driven class include all the functionality of BluetoothDeviceInfo.
I want to understand the big picture here and what would be approach to do such a thing.
Will be happy to hear you thoughts and guides on this.
Cheers
Try this:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b.DeviceAddress)).ToList();
You may need to provide a MyDeviceInfo constructor that takes a BluetoothDeviceInfo and copies all the properties.
Update
The code then becomes:
public class MyDeviceInfo : BluetoothDeviceInfo
{
private bool gpsSignal;
MyDeviceInfo(BluetoothDeviceInfo btInfo)
{
this.Authenticated = btInfo.Authenticated;
this.ClassOfDevice = btInfo.ClassOfDevice;
this.Connected = btInfo.Connected;
this.DeviceAddress = btInfo.DeviceAddress;
this.DeviceName = btInfo.DeviceName;
}
public MyDeviceInfo(string address) : base(address)
{
gpsSignal = false;
}
public bool GpsSignal { get { return gpsSignal; } set { gpsSignal = value;}}
}
And you use it like this:
IEnumerable<MyDeviceInfo> _discoveredCsaDevices = (cli.DiscoverDevices().Where(d => (d.DeviceName.StartsWith(...).Select (b => new MyDeviceInfo(b)).ToList();
Application note.
To the extent that inheritance works, use that. See Ned Stoyanov's answer. My answer below should only be used if the library class is sealed.
Problem #1 - Library class was sealed and wasn't dependent on an interface, therefore I cannot substitute it with my own class.
Solution: Make an interface anyway.
public interface IMyDeviceInfo : IComparable
{
BluetoothDeviceInfo(BluetoothAddress address);
bool Authenticated { get; }
ClassOfDevice ClassOfDevice { get; }
bool Connected { get; }
BluetoothAddress DeviceAddress { get; }
string DeviceName { get; set; }
...
}
Problem #2 - How can I stuff the library class under my interface?
Solution: Make an adapter.
public class DeviceInfoAdapter : IMyDeviceInfo
{
private BluetoothDeviceInfo m_theRealStuff;
// Allow yourself to bypass the abstraction to
// get down to the real object, because it may
// just be unavoidable in some cases.
// You may also mark it [Obsolete] or comment it out
// until you encounter a real need for it.
internal BluetoothDeviceInfo TheRealStuff
{
get { return m_theRealStuff; }
}
// Constructor. If the real stuff has been created by someone else.
public DeviceInfoAdapter(BluetoothDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// Constructor. A knock-off copy of the real stuff constructor.
public DeviceInfoAdapter(BluetoothAddress address)
{
m_theRealStuff = new BluetoothDeviceInfo(address);
}
// Imitate all properties and methods on the real stuff.
public bool Authenticated
{
get
{
return m_theRealStuff.Authenticated;
}
}
// ...
// Basically, for every publicly-accessible method or property,
// you just call the real stuff.
}
Problem #3 - How do I add extra properties to it?
Solution: Make a decorator.
public interface IMyDeviceInfoExtra : IMyDeviceInfo
{
bool GpsSignal { get; set; }
}
public class MyDeviceInfoWithGps : IMyDeviceInfoExtra
{
private IMyDeviceInfo m_theRealStuff;
private bool m_gpsSignal;
public MyDeviceInfoWithGps(IMyDeviceInfo theRealStuff)
{
m_theRealStuff = theRealStuff;
}
// the same thing again ... lots of code duplications
// The only new member here
public bool GpsSignal
{
get { return m_gpsSignal; }
set { m_gpsSignal = value; }
}
}
I have a method:
public ??? AuthManager.Login(Credentials credentials)
Here is a set of valid output values of this method:
Success (+accountId)
Failure: AccountLockedOut
Failure: UsernameNotFound
Failure: InvalidPassword (+failed attempt count)
Depending on the return type different views are shown to the user (yes, view for AccountLockedOut is different from InvalidPassword).
I could go with:
public class LoginAttemptResult {
public bool Succeeded { get; set; }
public AccountId AccountId { get; set; } // for when success
public LoginAttemptResultEnumType Result { get;set; } // Success, Lockedout, UsernameNotFound, InvalidPassword
public int FailedAttemptCount { get; set; } // only used for InvalidPassword
}
I don't like this and looking for a better solution. First, this results in a partially initialized object, two it violates interface segregation principle, three it violates SRP.
UPDATE: throwing exceptions is also not an elegant solution because InvalidPassword as I see it is not an exception. Failed DB connection is an exception. Null argument is an exception. InvalidPassword is a valid anticipated response.
I think better solution is to create a hierarchy of classes:
abstract class LoginAttemptResult
sealed class LoginSuccess : LoginAttemptResult { AccountId }
abstract class LoginFailure : LoginAttemptResult
sealed class InvalidPasswordLoginFailure : LoginFailure { FailedAttemptCount }
sealed class AccountLockedoutLoginFailure : LoginFailure
the caller of Login method then would have to do something like:
if (result is LoginSuccess) {
..."welcome back mr. account id #" + (result as LoginSuccess).AccountId
}
else if (result is InvalidPasswordLoginFailure ) {
..."you failed " + (result as InvalidPasswordLoginFailure).FailedAttemptCount + " times"
}
I don't see anything wrong (conceptually) with this approach (other than a number of classes it comes with).
What else is wrong with this approach?
Notice, this approach is essentially an F#'s discriminated union (DU) .
Is there a better way to model this? I already have several solutions that work - now I want an elegant solution that works.
I think your solution is OK in the case if result classes differs significantly and you need a separate class for each. But I'm not sure about that. Try this class for each result:
/// <summary>
/// Immutable, created by the server
/// </summary>
class LoginResult
{
/// <summary>
/// Null in the case of failure
/// </summary>
public int? Id { get; private set; }
/// <summary>
/// Null in the case of success
/// </summary>
public string FailReason { get; private set; }
/// <summary>
/// Always >= 1
/// </summary>
public int AttemptNumber { get; private set; }
public LoginResult(int id, int attemptNumber)
{
Id = id;
AttemptNumber = attemptNumber;
}
public LoginResult(string reason, int attemptNumber)
{
FailReason = reason;
AttemptNumber = attemptNumber;
}
}
I can imagine, that your authentication logic can be very complicated, and Id, FailReason and AttemptNumber are not only properties you'll need. In this case you need to present us more concrete example, we'll try to build abstractions that will fit your logic, if neccessary. In this particular case - no sense for abstraction.
Summary: instead of returning a value and decoding it - give Login a set of handlers so Login will call appropriate callback (think jQuery's ajax { success: ..., error: ... })
The consumer of the Login method will have to decode a response using essentially a switch statement. One way to refactor this code to eliminate that "switch" statement and also remove explosion of custom types is instead of asking Login method to return a discriminated union - we give Login method a set of thunks - one for each response.
(subtle point) Technically we don't get rid of custom classes, we simply replace them with generics, i.e. we replaced InvalidPasswordFailedLogin { int failedAttemptCount } with Action<int>. This approach also presents some interesting opportunities, for example Login can be handled async'ly more naturally. Testing on the other hand becomes little more obscure.
public class LoginResultHandlers {
public Action<int> InvalidPassword { get; set; }
public Action AccountLockedout { get; set; }
public Action<AccountId> Success { get; set; }
}
public class AccountId {}
public class AuthManager {
public void Login(string username, string password, LoginResultHandlers handler) {
// if (...
handler.Success(new AccountId());
// if (...
handler.AccountLockedout();
// if (...
handler.InvalidPassword(2);
}
}
public class Application {
public void Login() {
var loginResultHandlers = new LoginResultHandlers {
AccountLockedout = ShowLockedoutView,
InvalidPassword = (failedAttemptCount) => ShowInvalidPassword(failedAttemptCount),
Success = (accountId) => RedirectToDashboard(accountId)
};
new AuthManager().Login("bob", "password", loginResultHandlers);
}
private void RedirectToDashboard(AccountId accountId) {
throw new NotImplementedException();
}
private void ShowInvalidPassword(int failedAttemptCount) {
throw new NotImplementedException();
}
private void ShowLockedoutView() {
throw new NotImplementedException();
}
}
You could make return a Tuple
public Tuple<T1,T2> AuthManager.Login(Credentials credentials){
//do your stuff here
return new Tuple<T1,T2>(valueOfT1,valueOfT2);
}
If you make your LoginAttemptResult class abstract, then you can add an abstract property Message that will force your child classes to implement it.
public abstract class LoginAttemptResult
{
public abstract string Message { get; }
// any other base methods/properties and abstract methods/properties here
}
Then, your children could look like this:
public class LoginSuccess : LoginAttemptResult
{
public override string Message
{
get
{
return "whatever you use for your login success message";
}
}
}
With that, your Login method could just return a LoginAttemptResult
public LoginAttemptResult AuthManager.Login(Credentials credentials)
{
// do some stuff
}
And then your caller would just call your LoginAttemptResult.Message (or whatever other things you needed it to do):
var loginResult = AuthManager.Login(credentials);
var output = loginResult.Message;
Similarly, if you needed to have some other method associated with your LoginAttemptResult based on the child type, you could define it as an abstract method in your base class, implement it in your child classes, and then call it the exact same way.
Another possible approach is to create a class that encapsulates the Login process and its results, like this:
public interface ILoginContext
{
//Expose whatever properties you need to describe the login process, such as parameters and results
void Login(Credentials credentials);
}
public sealed class AuthManager
{
public ILoginContext GetLoginContext()
{
return new LoginContext(this);
}
private sealed class LoginContext : ILoginContext
{
public LoginContext(AuthManager manager)
{
//We pass in manager so that the context can use whatever it needs from the manager to do its job
}
//...
}
}
Basically what this design implies is that logging in has become a complex enough operation that a single method is no longer an appropriate encapsulation. We need to return a complex result and might want to include more complex parameters. Because the class is now responsible for the behavior and not just representing data, it's less likely to be considered a violation of SRP; it's just a somewhat complex class for a somewhat complex operation.
Note that you might also make the LoginContext implement IDisposable if it has a natural transactional scope.
your security api should not be exposing so much information.
The API you posted provides no useful information to a client, other than to aid an attacker in trying to hijack an account. Your login method should provide only pass/fail information and the token that can be passed on to any authorization mechanism you need.
// used by clients needing to authenticate
public interfac ISecurity {
AuthenticationResponse Login(Credentials credentials);
}
// the response from calling ISecurity.Login
public class AuthenticationResponse {
internal AuthenticationResponse(bool succeeded, AuthenticationToken token, string accountId) {
Succeeded = succeeded;
Token = token;
}
// if true then there will be a valid token, if false token is undefined
public bool Succeeded { get; private set; }
// token representing the authenticated user.
// document the fact that if Succeeded is false, then this value is undefined
public AuthenticationToken Token { get; private set; }
}
// token representing the authenticated user. simply contains the user name/id
// for convenience, and a base64 encoded string that represents encrypted bytes, can
// contain any information you want.
public class AuthenticationToken {
internal AuthenticationToken(string base64EncodedEncryptedString, string accountId) {
Contents = base64EncodedEncryptedString;
AccountId = accountId;
}
// secure, and user can serialize it
public string Contents { get; private set; }
// used to identify the user for systems that aren't related to security
// (e.g. customers this user has)
public string AccountId { get; private set; }
}
// simplified, but I hope you get the idea. It is what is used to authenticate
// the user for actions (i.e. read, write, modify, etc.)
public interface IAuthorization {
bool HasPermission(AuthenticationToken token, string permission);
}
You will notice that this API does not have log in attempts. The client should not care about the rules involved with logging in. The implementer of the ISecurity interface should keep up with log in attempts, and return fail when a successful set of credentials has been passed in, but the number of attempts has been exceedeed.
A simple message on failure should read something along the lines of:
Could not log you on at this time. Check that your username and/or password are correct, or please try again later.
Here is a solution that satisfies all my requirements (readability, testability, discoverability and esthetics).
Code (notice the implementation is little different from original task, but concept remains):
public class AuthResult {
// Note: impossible to create empty result (where both success and failure are nulls).
// Note: impossible to create an invalid result where both success and failure exist.
private AuthResult() {}
public AuthResult(AuthSuccess success) {
if (success == null) throw new ArgumentNullException("success");
this.Success = success;
}
public AuthResult(AuthFailure failure) {
if (failure == null) throw new ArgumentNullException("failure");
this.Failure = failure;
}
public AuthSuccess Success { get; private set; }
public AuthFailure Failure { get; private set; }
}
public class AuthSuccess {
public string AccountId { get; set; }
}
public class AuthFailure {
public UserNotFoundFailure UserNotFound { get; set; }
public IncorrectPasswordFailure IncorrectPassword { get; set; }
}
public class IncorrectPasswordFailure : AuthResultBase {
public int AttemptCount { get; set; }
}
public class UserNotFoundFailure : AuthResultBase {
public string Username { get; set; }
}
Notice how AuthResult correctly models a heterogeneous and hierarchical nature of the function range.
And if you add a following implicit operator:
public static implicit operator bool(AuthResultBase result) {
return result != null;
}
you can use result as follows:
var result = authService.Auth(credentials);
if (result.Success) {
...
}
which reads (arguably) better than:
if (result.Success != null) {
...
}
I have a lot of similar classes generated by svcutil from some external WSDL file. Any class has a Header property and string property which named class name + "1".
For instance, I have classes: SimpleRequest that has Header property and SimpleRequest1 property.
Another one is ComplexRequest that has Header property and ComplexRequest1 property.
So, I want to create a common interface for such classes. So, basically I can define something like that:
interface ISomeRequestClass {
string Header;
// here is some definition for `class name + "1"` properties...
}
Is it possible to define such member in interface?
Here is post edit goes...
Here is sample of generated class:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class SimpleRequest
{
public string Header;
[System.ServiceModel.MessageBodyMemberAttribute(Name="SimpleRequest", Namespace="data", Order=0)]
public SimpleRequestMsg SimpleRequest1;
public SimpleRequest()
{
}
public SimpleRequest(string Header, SimpleRequestMsg SimpleRequest1)
{
this.Header = Header;
this.SimpleRequest1 = SimpleRequest1;
}
}
POST EDIT 2
I changed definition of this annoying +1 property to represent real actual picture. It's all has different class types. So how can I pull it out to common interface?
POST EDIT 3
Here is coupled question that could bring more clarify.
EDIT (after seeing your code sample): Technically speaking, your code does not have a Header property, it has a Header field. This is an important difference, since you cannot specify fields in an interface. However, using the method described below, you can add properties to your classes that return the field values.
Is it possible to define such member in interface?
No, interface names cannot be dynamic. Anyway, such an interface would not be very useful. If you had an instance of class ISomeRequestClass, what name would you use to access that property?
You can, however, use explicit interface implementation:
interface ISomeRequestClass {
string Header { get; set; }
string ClassName1 { get; set; }
}
class SomeClass : ISomeRequestClass {
string Header { ... }
string SomeClass1 { ... }
// new: explicit interface implementation
string ISomeRequestClass.ClassName1 {
get { return SomeClass1; }
set { SomeClass1 = value; }
}
}
You could define your interface more generally:
interface ISomeRequestClass {
string HeaderProp {get; set;}
string Prop {get; set;}
}
And your concrete classes could be extended (in an extra code file) by mapping interface members to class fields like so:
public partial class SimpleRequest : ISomeRequestClass
{
public string HeaderProp
{
get
{
return Header;
}
set
{
Header = value;
}
}
public string Prop
{
get
{
return SimpleRequest1;
}
set
{
SimpleRequest1= value;
}
}
}
Putting aside for a moment the naming of your classes and properties.
If you're looking to create an interface with a property relevant to your specific +1 type, you have a couple of options.
Use a base class for your +1's
If both of your +1 classes inherit from the same base class you can use this in your interface definition:
public interface IFoo
{
[...]
PlusOneBaseType MyPlusOneObject{get;set;}
}
Create a generic property on your interface
This method allows you to specify the type for the +1 property as a generic parameter:
public interface IFoo<TPlusOneType>
{
[...]
TPlusOneType MyPlusOneObject{get;set;}
}
Which you might use like:
public class SimpleRequest : IFoo<SimpleRequest1>
{
[...]
}
Update
Given that your classes are partial classes, you could always create a second (non machine generated) version of the partial class that impliments your interface.
You mentioned svcutil so I assume you are using these classes as WCF DataContracts?
If that is the case then you could make use the name property of DataMemberAttribute.
interface IRequest
{
string Header { get; set; }
string Request1 { get; set; }
}
[DataContract]
class SimpleRequest : IRequest
{
[DataMember]
public string Header { get; set; }
[DataMember(Name="SimpleRequest1"]
public string Request1 { get; set; }
}
[DataContract]
class ComplexRequest : IRequest
{
[DataMember]
public string Header { get; set; }
[DataMember(Name="ComplexRequest1"]
public string Request1 { get; set; }
}
If you are concerned giving yourself more work when you regenerate the code at some point in the future, then I recommend you write a PowerShell script to do this transformation automatically. After all svcutil is just a script written by some guy at Microsoft. It is not magic or "correct" or "standard". Your script can make a call to scvutil and then make a few quick changes to the resulting file.
EDIT (After seeing your edit)
You are already using MessageBodyMemberAttribute's Name property so just change this:
public string SimpleRequest1;
To
public string Request1;
Do you actually need these classes to have a common interface? I'd be tempted to instead create a wrapper interface (or just a concrete class) which could then use reflection to access the fields in question:
// TODO: Make this class implement an appropriate new interface if you want
// to, for mocking purposes.
public sealed class RequestWrapper<TRequest, TMessage>
{
private static readonly FieldInfo headerField;
private static readonly FieldInfo messageField;
static RequestWrapper()
{
// TODO: Validation
headerField = typeof(TRequest).GetField("Header");
messageField = typeof(TRequest).GetField(typeof(TRequest).Name + "1");
}
private readonly TRequest;
public RequestWrapper(TRequest request)
{
this.request = request;
}
public string Header
{
get { return (string) headerField.GetValue(request); }
set { headerField.SetValue(request, value); }
}
public TMessage Message
{
get { return (TMessage) messageField.GetValue(request); }
get { messageField.SetValue(request, value); }
}
}
You could use expression trees to build delegates for this if the reflection proves too slow, but I'd stick to a simple solution to start with.
The advantage of this is that you only need to write this code once - but it does mean creating a wrapper around the real request objects, which the partial class answers don't.
What's the first line of the following code called?
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual IController Controller
{
get { return controller; }
set { controller = value; }
}
It's called an attribute. Attributes are used to describe properties, methods, etc. They serve to provide metadata, among other things.
In this case, the DesignerSerializationVisibility.Hidden attribute means that the Controller property isn't visible to the design-time serializer.
Positional parameters are parameters of the constructor of the attribute. They are mandatory and a value must be passed every time the attribute is placed on any program entity. On the other hand Named parameters are actually optional and are not parameters of the attribute's constructor.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false,
Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
this.verion = "No Version is defined for this class";
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
protected String version;
public String Version
{
get
{
return this.version;
}
//if we ever want our attribute user to set this property,
//we must specify set method for it
set
{
this.verion = value;
}
}
}
[Help("This is Class1")]
public class Class1
{
}
[Help("This is Class2", Version = "1.0")]
public class Class2
{
}
[Help("This is Class3", Version = "2.0",
Description = "This is do-nothing class")]
public class Class3
{
}
more...
In my current project I need to be able to have both editable and read-only versions of classes. So that when the classes are displayed in a List or PropertGrid the user is not able to edit objects they should not be allowed to.
To do this I'm following the design pattern shown in the diagram below. I start with a read-only interface (IWidget), and then create an edtiable class which implements this interface (Widget). Next I create a read-only class (ReadOnlyWidget) which simply wraps the mutable class and also implements the read only interface.
I'm following this pattern for a number of different unrelated types. But now I want to add a search function to my program, which can generate results that include any variety of types including both mutable and immutable versions. So now I want to add another set of interfaces (IItem, IMutableItem) that define properties which apply to all types. So IItem defines a set of generic immutable properties, and IMutableItem defines the same properties but editable. In the end a search will return a collection of IItems, which can then later be cast to more specific types if needed.
Yet, I'm not sure if I'm setting up the relationships to IMutable and IItem correctly. Right now I have each of the interfaces (IWidget, IDooHickey) inheriting from IItem, and then the mutable classes (Widget, DooHickey) in addition also implement IMutableItem.
Alternatively, I was also thinking I could then set IMutableItem to inherit from IItem, which would hide its read-only properties with new properties that have both get and set accessors. Then the mutable classes would implement IMutableItem, and the read-only classes would implement IItem.
I'd appreciate any suggestions or criticisms regarding any of this.
Class Diagram
Code
public interface IItem
{
string ItemName { get; }
}
public interface IMutableItem
{
string ItemName { get; set; }
}
public interface IWidget:IItem
{
void Wiggle();
}
public abstract class Widget : IWidget, IMutableItem
{
public string ItemName
{
get;
set;
}
public void Wiggle()
{
//wiggle a little
}
}
public class ReadOnlyWidget : IWidget
{
private Widget _widget;
public ReadOnlyWidget(Widget widget)
{
this._widget = widget;
}
public void Wiggle()
{
_widget.Wiggle();
}
public string ItemName
{
get {return _widget.ItemName; }
}
}
public interface IDoohickey:IItem
{
void DoSomthing();
}
public abstract class Doohickey : IDoohickey, IMutableItem
{
public void DoSomthing()
{
//work it, work it
}
public string ItemName
{
get;
set;
}
}
public class ReadOnlyDoohickey : IDoohickey
{
private Doohickey _doohicky;
public ReadOnlyDoohickey(Doohickey doohicky)
{
this._doohicky = doohicky;
}
public string ItemName
{
get { return _doohicky.ItemName; }
}
public void DoSomthing()
{
this._doohicky.DoSomthing();
}
}
Is it OK to create another object when you need a readonly copy? If so then you can use the technique in the included code. If not, I think a wrapper is probably your best bet when it comes to this.
internal class Test
{
private int _id;
public virtual int ID
{
get
{
return _id;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
if (ReadOnly)
{
throw new InvalidOperationException("Cannot set properties on a readonly instance.");
}
}
}
public bool ReadOnly { get; private set; }
public Test(int id = -1, string name = null)
: this(id, name, false)
{ }
private Test(int id, string name, bool readOnly)
{
ID = id;
Name = name;
ReadOnly = readOnly;
}
public Test AsReadOnly()
{
return new Test(ID, Name, true);
}
}
I would suggest that for each main class or interface, there be three defined classes: a "readable" class, a "changeable" class, and an "immutable" class. Only the "changeable" or "immutable" classes should exist as concrete types; they should both derive from an abstract "readable" class. Code which wants to store an object secure in the knowledge that it never changes should store the "immutable" class; code that wants to edit an object should use the "changeable" class. Code which isn't going to write to something but doesn't care if it holds the same value forever can accept objects of the "readable" base type.
The readable version should include public abstract methods AsChangeable(), AsImmutable(), public virtual method AsNewChangeable(), and protected virtual method AsNewImmutable(). The "changeable" classes should define AsChangeable() to return this, and AsImmutable to return AsNewImmutable(). The "immutable" classes should define AsChangeable() to return AsNewChangeable() and AsImmutable() to return this.
The biggest difficulty with all this is that inheritance doesn't work terribly well if one tries to use class types rather than interfaces. For example, if one would like to have an EnhancedCustomer class which inherits from BasicCustomer, then ImmutableEnhancedCustomer should inherit from both ImmutableBasicCustomer and ReadableEnhancedCustomer, but .net doesn't allow such dual inheritance. One could use an interface IImmutableEnhancedCustomer rather than a class, but some people would consider an 'immutable interace' to be a bit of a smell since there's no way a module that defines an interface in such a way that outsiders can use it without also allowing outsiders to define their own implementations.
Abandon hope all ye who enter here!!!
I suspect that in the long run your code is going to be very confusing. Your class diagram suggests that all properties are editable (or not) in a given object. Or are your (I'm)mutable interfaces introducing new properties that are all immutable or not, separate from the "core"/inheriting class?
Either way I think you're going to end up with playing games with property name variations and/or hiding inherited properties
Marker Interfaces Perhaps?
Consider making all properties in your classes mutable. Then implement IMutable (I don't like the name IItem) and IImutable as a marker interfaces. That is, there is literally nothing defined in the interface body. But it allows client code to handle the objects as a IImutable reference, for example.
This implies that either (a) your client code plays nice and respects it's mutability, or (b) all your objects are wrapped by a "controller" class that enforces the given object's mutability.
Could be too late :-), but the cause "The keyword 'new' is required on property because it hides property ..." is a bug in Resharper, no problem with the compiler. See the example below:
public interface IEntityReadOnly
{
int Prop { get; }
}
public interface IEntity : IEntityReadOnly
{
int Prop { set; }
}
public class Entity : IEntity
{
public int Prop { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var entity = new Entity();
(entity as IEntity).Prop = 2;
Assert.AreEqual(2, (entity as IEntityReadOnly).Prop);
}
}
Same for the case without interfaces. The only limitation, you can't use auto-properties
public class User
{
public User(string userName)
{
this.userName = userName;
}
protected string userName;
public string UserName { get { return userName; } }
}
public class UserUpdatable : User
{
public UserUpdatable()
: base(null)
{
}
public string UserName { set { userName = value; } }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var user = new UserUpdatable {UserName = "George"};
Assert.AreEqual("George", (user as User).UserName);
}
}