I'm working with a third party web service that exposes a status property on one of its classes but this property is in fact another class itself.
Whilst this is no great shakes I'm trying to make use of this web service easier for other developers in the company since the web service is abstracted away and we have our own adapter classes exposing just the properties/methods we need and I have been trying to come up with a way that will allow me to treat the status object much like a enum
What I would like to end up with is something like object.status = StatusAdapter.<value>
Before anybody says 'simply use an enum' the reason I am not simply using an enum is that the status data that the web service object represents can be added to by a user at any time which means that I'd have to change the class library and re-deploy to all applications that use it.
Any ideas?
Edit
To clarify I want the end developers to be able to do the following, along the lines of an enum when StatusAdapter is not an enum but populated dynamically at run time.
If(foo.Status == StatusAdapter.NotStarted){...}
Use Interface. That should do the job.
Take for example, do this
public interface IStatus
{
}
public class SuccessStatus: IStatus
{
}
public class FailStatus: IStatus
{
}
in your class, you can do this:
public class CheckWebService
{
public IStatus Status
{get;set;}
}
So anyone using your class can do this easily:
var checking = new CheckWebService();
checking.Status=new SuccessStatus();
Or define their own status which is inherited from IStatus and use it.
In this way you don't have to redeploy your code and yet still able to let users define their own statuses.
The only way would be to have a number of properties on StatusAdapter which are of type StatusAdapter and return different values of StatusAdapter
Related
I know this might be an opinion-based question, but, I'd rather to ask as there might be some design principle for this.
I'm having a .net C# web API application to expose few APIs to retrieve some data from a database. I'm also using mediateR on this project. The APIs, they all get one request object but all of them have exact same properties. Imagine, we have a BaseProduct class from which ProductA, ProductB, and ProductChave been inherited in the domain project. Now, I need to expose APIs to return these three objects to the users. Here's an example of two of the request objects.
With Inheritance:
public abstract class BaseGetProductRequest { // the props here }
public class GetProductARequest : BaseGetProductRequest, IRequest<GetProductAResponse> { }
public class GetProductBRequest : BaseGetProductRequest, IRequest<GetProductBResponse> { }
public class GetProductAResponse { public ProductA[] Products {get; set;} }
Each of the above requests also has its own request handler class.
With using generics: (BaseProduct is a domain object class from which different product types are inherited)
public class GetProductRequest<TProductType> : IRequest<TProductType[]> where TProductType : BaseProductType { // all props in here }
Which will be used like this in an API:
public async Task<ProductA[]> Get([FromRoute] GetProductRequest<ProductA> request) { // API body }
So, the question is: Which one the following would be a better approach to take from a design point of view?
To take the Inheritance approach as above
Or to implement the requests and request handlers using generics so we'll end up with less files
Personally, I would prefer the first approach as I want to literally have separate request objects for each API, this way it looks cleaner to me besides that would be consistent with the rest of the code as well (as not all the request objects can be implemented generically). Besides, if by any chance in the future there is a need to add a type-specific property for a request object, then, our code will be more flexible with that change.
Is there like any specific design guidelines which recommends for example taking one over another? Thanks for your opinions in advance.
Sure the inheritance approach will give your project a higher performance, due to the re-usability of compiled requests
Previous Post removed; Updated:
So I have a unique issue, which is possibly fairly common though. Properties are quite possibly are most commonly used code; as it requires our data to keep a constant value storage. So I thought how could I implement this; then I thought about how easy Generics can make life. Unfortunately we can't just use a Property in a Generic without some heavy legwork. So here was my solution / problem; as I'm not sure it is the best method- That is why I was seeking review from my peers.
Keep in mind the application will be massive; this is a very simple example.
Abstract:
Presentation Layer: The interface will have a series of fields; or even data to go across the wire through a web-service to our database.
// Interface:
public interface IHolder<T>
{
void objDetail(List<T> obj);
}
So my initial thought was an interface that will allow me to Generically handle each one of my objects.
// User Interface:
public class UI : IHolder
{
void objDetail(List<object> obj)
{
// Create an Instance
List<object> l = new List<object>();
// Add UI Fields:
l.Add(Guid.NewGuid());
l.Add(txtFirst.Text);
l.Add(txtLast.Text);
// l to our obj
obj = l;
return;
}
}
Now I have an interface; which has been used by our UI to put information in. Now; this is where the root of my curiosity has been thrown into the mixture.
// Create an Object Class
public class Customer : IHolder
{
// Member Variable:
private Guid _Id;
private String _First;
private String _Last;
public Guid Id
{
get { return _Id; }
set { _Id = value; }
}
public String First
{
get { return _First; }
set { _First = value; }
}
public String Last
{
get { return _Last; }
set { _Last = value; }
}
public virtual objDetail(List<Customer> obj)
{
// Enumerate through List; and assign to Properties.
}
}
Now this is where I thought it would be cool; if I could use Polymorphism to use the same interface; but Override it to do the method differently. So the Interface utilizes a Generic; with the ability to Morph to our given Object Class.
Now our Object Classes; can move toward our Entity interface which will handle basic Crud Operation.
I know this example isn't the best for my intention; as you really don't need to use Polymorphism. But, this is the overall idea / goal...
Interface to Store Presentation Layer UI Field Value
Implement the Properties to a Desired Class
Create a Wrapper Around my Class; which can be Polymorphed.
Morphed to a Generic for Crud Operation
Am I on the right path; is this taboo? Should I not do this? My application needs to hold each instance; but I need the flexibility to adapt very quickly without breaking every single instance in the process. That was how I thought I could solve the issue. Any thoughts? Suggestions? Am I missing a concept here? Or am I over-thinking? Did I miss the boat and implement my idea completely wrong? That is where I'm lost...
After pondering on this scenario a bit, I thought what would provide that flexibility while still ensuring the code is optimized for modification and business. I'm not sure this is the right solution, but it appears to work. Not only does it work, it works nicely. It appears to be fairly robust.
When is this approach useful? Well, when you intend to decouple your User Interface from your Logic. I'll gradually build each aspect so you can see the entire structure.
public interface IObjContainer<T>
{
void container(List<T> object);
}
This particular structure will be important. As it will store all of the desired content into it.
So to start you would create a Form with a series of Fields.
Personal Information
Address Information
Payment Information
Order Information
So as you can see all of these can be separate Database Tables, but belong to a similar Entity Model you are manipulating. This is quite common.
So a Segregation Of Concern will start to show slightly, the fields will be manipulated and passed through an Interface.
public interface IPersonalInformation
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
So essentially the Interface is passing its variable, to the Interface. So you would culminate an interface to handle that entire form or individual interfaces that you wish to call so that they remain reusable.
So now you have a series of Interfaces, or a single once. But it contains all these variables to use. So you would now create a class:
public class CustomerProperties: IPersonalInformation, IOrderInformation
{
// Implement each Interface Property
}
Now you've created a container that will hold all of your values. What is nifty about this container is you can reuse the same values for another class in your application or choose different ones. But it will logically separate the User Interface.
So essentially this is acting similar to a Repository.
Now you can take these values and perform the desired logic. What becomes wonderful now, is after you've performed your logic you pass the object into our Generic List. Then you simply implement that method in another class for your goal and iterate through your list.
The honesty is it appears to work well and decouple nicely. I feel that it was a lot of work to do something similar to a normal Repository and Unit Of Work, this answers the question but weather or not it is ideal for your project I would look into Repository, Unit Of Work, Segregation Of Concern, Inversion Of Control, and Dependency Injection. They may do this same approach cleaner.
Update:
I thought about it after I wrote this up, I noticed you could actually implement those property values into the Generic List structure bypassing a series of interfaces; but that would introduce consistency issues as you'd have to be aware of what data is being passed in each time, in order. It's possible, but may not be ideal.
Is it possible to give different view of a Class . For example , i have Account class , i want expose this data using WCF. For different method call i want expose different property of Account class.Suppose for particular call i want expose only UserName and Password, for
another call i want expose Email and Address. Should i have to write different class or
i can expose needed property to client
If one usage is WCF and another usage is internal to your app, then you can annotate the class appropriately with [DataMember] such that only the desired properties are exposed. If you have two different WCF scenarios, then I would introduce a new class (or classes) to represent each set of return data, probably adding an implicit conversion operator (from the entity to the DTO), so that you can do:
public CustomerLite GetCustomer(int id) {
Customer cust = SomeTier.GetCustomer(id);
return cust; // note cust is Customer but we are returning CustomerLite
}
You could use a DataContract with DataMember attributes, but that allows you to produce only one serialised view of a class. You would probably want to create smaller ViewModel classes, possibly using AutoMapper to handle all the mapping code for you.
If you want to expose multiple views of the same Account class, the answer is no (that I'm aware of). Using the default DataContractSerializer, you can control which members are presented to the user only in a declarative manner. This would allow you to customize the user's view in one way, but not multiples.
Instead, you can create one individual data contract class (which might take an Account as a constructor argument) for each "view" you wish to expose.
You could achieve this using interfaces as "views". For example create a UsernamePassword interface with methods or properties to access username and password and have the Account class implement this interface. You can then pass this interface around and the users of it will be unaware of the other methods and properties in the account class.
interface IUsernamePassword
{
string Username { get; set; }
string Password { get; set; }
}
class Account : IUsernamePassword
{
public string Username { get; set; }
public string Password { get; set; }
}
Always, always, always use a message class (aka DTO) when using any service that is hosted outside of your app domain.
I use to have a slide in all my presentations on WCF that stated Message Classes != Business Classes, but I've since found a better way to explain it.
This isn't Star Trek people. You Can't Fax a Cat (a picture is worth a 1000 words).
I'm starting to see the value of Interfaces vs. lets say an Abstract class.
Currently I'm working on a PayPal Wrapper project. We'll also be probably doing a Google Payments, BillMeLater, and Amazon wrapper. I've been asked to identify some commonalities (methods, properties, whatever) that we could use across the board, in most any Web Service SOAP Wsdl Wrapper project for any web services we do.
So as I was coding out my PayPal wrappers, I created a new class to hold Errors received back from any PayPal response:
public class ApiError
{
#region Constructors
/// <summary>
/// Disallow default instantiation.
/// </summary>
private ApiError()
{
}
internal ApiError(ErrorType error)
{
if(error.ErrorCode != null)
{
this._errorCode = error.ErrorCode;
}
}
#endregion
#region member variables
private string _errorCode = string.Empty;
private string _erorMessage = string.Empty;
#endregion
#region Properties
public string ErrorCode
{
get { return _errorCode; }
set { _errorCode = value; }
}
public string ErrorMessage
{
get { return _errorMessage; }
set { _errorMessage = value; }
}
#endregion
}
Anyway, I said hey, these ErrorMessage and ErrorCode properties are most likely going to be in every third party API. So why not create an Interface in a new project called [MyCompany].WebServices.Common and in that interface add those 2 properties. Then any class wrapper that I create that has functionality to make API proxy calls can implement this interface and then I know any of those kinds of wrapper classes in any of our web service projects will be guaranteed to have these kind of properties in them that will be impolemented and filled with any errors that come back from an API response.
And if they do, then that's great because I can then start to create some helper methods that we can use across the board if I can somehow take in a generic response object and fill the array of errors and set the property.
Anyway, my problem is, I'm new to interfaces a litte. So the error array property from above for example is of a custom type.
Well if I create interface in a seperate physical project, I can't use that custom type because it doesn't exist..it only exists so far in my PayPal wrapper project.
So then when stubbing this interface out, how would I handle this?
namespace [MyCompany].WebServices.Common
{
interface IRequest
{
public ApiError Type { get; set; } //whoops, that's a custom type that this project does not know about (ApiError)
}
}
You should consider that the ApiErrors are going to depend on the particular web service implementation. So how would a client that is using only interfaces going to use the ApiErrors if they are implementation-specific?
It can't - because this would mean that its coupled to this particular implementation.
Instead, you need to abstract away from the specific API error codes, and define your own abstract error codes.
Every Problem in Software can be Solved with Another Layer of Indirection!!! Just add another interface called IAPIError that you implement for each pay service error type.
interface IRequest
{
public IApiError Type { get; set; }
}
You could put your shared types in a separate, shared assembly: [MyCompany].WebServices.Shared
Edit
Come to think of it, you already have that. [MyCompany].WebServices.Common should be as good a place as any for your shared types. Just move it there. Or am I misunderstanding what you want to do?
The exact error numbers and messages will be very specific for each provider. Therefore, while a common interface can be made, it will not provide enough abstraction to handle errors in a meaningful way.
I'd add another abstraction by defining the expected errors (one of which is "unknown error" as catch-all for unexpected errors) as separate class or even as set of Exceptions. Then, have each provider return or use those, which is already compatible with your application and allows you to handle common errors for all providers the same way.
Put those common types into a separate assembly, which is a pure "interface" assembly used by both the providers and the actual code using them. Therefore you'll be able to loosely couple the providers without having to add references to them in your main application (allowing you to add or modify providers without recompiling the application).
I have a Silverlight 3 application which gets data from a web service. When I add a reference to my web service, all the classes used by the web service are defined in a proxy class. So far, so good... Now, I would like to use the DataForm offered in Silverlight 3. To use that component, I must add metadata to my class (e.g. see code below).
public class Movie : IEditableObject
{
public int MovieID { get; set; }
[Display(Name="The Movie Name")]
public string Name { get; set; }
}
My question is, considering the class Movie is defined in the proxy class generated by .NET, how do I add the attributes/metadeta to the properties of the Movie class without modifying the class generated?
Thanks
In short; you don't. Don't edit the generated code, since your changes will be lost the next time it is generated.
Instead, create your own Movie class inside your application and create methods that translates the generated Movie proxy class to your internal Movie class (and back), and then make your internal class have the desired behavior. I usually wrap this together at a low level, so that most of my code never see the generated proxy classes.
If converting your web service to use .NET RIA Services is a possibility you can use this technique to apply attributes to properties without using a wrapper class:
http://blogs.msdn.com/brada/archive/2009/07/21/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-part-7-services-based-data-store.aspx
With RIA Services you apply the attributes on the server side - the code generator is intelligent enough to pick them up and apply them on the client side as well when it generates code.
If in case you really need to add something to the generated class, you can still use the partial class to achieve without modifying anything within the generated class.