When should I use params Object[] versus Dictionary<String, Object>? - c#

I'm defining an API as an interface which we'll call IFoo and I want to define a method Bar()
This method Bar() will take one required argument and then some arbitrary number of other arguments. The interpretation of these other arguments will be up to implementors of IFoo
For this scenario is it more appropriate to define my interface using params or using Dictionary<String, Object> e.g.
public interface IFoo
{
bool Bar(String id, params Object[] params);
}
Or
public interface IFoo
{
bool Bar(String id, Dictionary<String, Object> params);
}
It seems like the former is easier for users to invoke but the latter is more explicit in its intentions since with the former you'd have to specify the parameters in a specific order for the implementation to interpret them properly while with the latter you are essentially doing named parameters.
So questions:
Which form should I be using (and why?) - is one of these considered best practice over another?
Are there specific advantages to one style versus the other that I should be aware of? Is one of these considered a code smell?
Is there an alternative pattern that would achieve the same thing in a different/nicer way?
For the record I am aware of named parameters in .Net 4.0 but this code needs to be compilable on .Net 3.5 so can't use any .Net 4.0+ functionality
Edit
Just to add more detail on what my IFoo and Bar() methods are actually representing because someone asked.
IFoo represents some storage subsystem and Bar() is actually a create operation. Depending on the storage subsystem Bar() could require no parameters other than the ID or it could require many parameters.
Edit 2
So in response to #Kirk Woll's comment and #Fernando's answers here's more information.
I will likely never invoke IFoo.Bar() myself, this interface is part of an open source framework. 3rd party devs will be implementing IFoo and end users will be invoking specific instances of it, the point of having IFoo at all is to make it easier for users to migrate their applications between storage subsystems because they can code to interfaces rather than specific implementations as far as humanly possible.
In the simplest case the underlying storage subsystem only has one form of store so no parameters will be required other then the ID. In the complex case the storage subsystem may allow multiple types of store and each type of store may permit arbitrarily complex set of configuration parameters e.g. index size, persistence, transaction behavior, indexing strategy, security and ACL considerations etc.
I agree with #Fernando that maybe something more polymorphic may make sense, maybe polymorphism combined with generics and type restrictions may be best e.g.
public interface IFoo
{
bool Bar<T>(T parameters) where T : IBarConfig;
}
public interface IBarConfig
{
String ID { get; set; }
}
Then with an implementation like so:
public class MyFoo
{
bool Bar<T>(T config) where T : MyBarConfig
{
//Implementation
}
}
public class MyBarConfig : IBarConfig
{
public String ID { get; set; }
public long IndexSegmentSize { get; set; }
//Etc...
}
This is off the top of my head so not sure if it is actually legal to define Bar() in MyFoo with a different type restriction then the interface it implements?

You need to decide if you need to search or be able to retrieve an Object from the params collection/Array.
When using Object[] params, There is no indexing on the Objects. You need to iterate the whole collection to find an item (by its key).
When using a Dictionary<String, Object>, your Objects are indexed by their key, and its always easy to search/query by the key.
Depending on your need, you need to decide your Approach.
Dictionary is faster for searches, but there is an overhead to create the indexes.

The dictionary approach has another problem: typos. You'll probably need to define a lot of constants to use as keys to avoid this problem.
Why not going for a polymorphic solution?
public interface IFoo {
void Bar(FooData data);
}
public abstract class FooData {
public int Id {get;set;}
}
public class MyFooData1 : FooData {
public string SomeProperty {get;set;}
//...
}
public class MyFoo : IFoo {
public void Bar(FooData data) {
var myData = (MyFooData1)data;
//...
}
}
public class MyFooData2 : FooData {
public int SomeOtherProperty {get;set;}
//...
}
public class MyFoo2 : IFoo {
public void Bar(FooData data) {
var myData = (MyFooData2)data;
//...
}
}
You'll end up with more smaller classes, but they are easy to test and extend.
Update
#RobV you can't change the type restriction if you're implementing an interface, but, if you put your type parameter at the interface declaration, you may accomplish what you're trying to do:
public interface IFoo<T> where T : IBarConfig {
void Bar(T parameters);
}
public class MyBarConfig: IBarConfig {
public String ID { get; set; }
public long IndexSegmentSize { get; set; }
}
public class MyFoo : IFoo<MyBarConfig> {
public void Bar(MyBarConfig config) {
//Implementation
}
}

params provide easier to write/read code compared to Dictionary if you need to write them inline. I.e. imaging constructing dictionary for every call to String.Format - code will be unreadable. On other hand if you already have dictionary of parameter - ok to use it.
I would recommend to reconsider API and see if you can accept IEnumerable, or even better IEnumerable<T> as arguments. Unfortunately with such generic IFoo name of sample it is not possible to see if such approach would work.

Which form should I be using (and why?) - is one of these considered best practice over another? ---> You should use the second one, because it's a lot less error prone than the second one.
Regarding the alternative pattern, there is surely a way to implement this in a nicer way. Can you tell us what your problem actually is? instead of using IFoo and Bar? I can't suggest anything else unless I know exactly what you are trying to do, and why...

The fact that you mention optional parameters makes me think the IDictionary<string,object> approach would be better - that's your best approach to give that kind of interface in .Net 3.5. You could just ask for object and do something like what MVC does for htmlAttributes (using reflection to turn the anonymous object into an IDictionary<string,object>).
The scenario where I'd prefer the params object[] approach are ones where trying to give them names in every situation would just be weird/impossible, like for string.format.

Related

Accepting multiple similar entities in a Method - Elegant solution

I have two data entities, which are almost similar, design is something like:
public Class Entity1 : Base
{
public int layerId;
public List<int> Groups;
}
Difference is Entity1 has an extra collection of integer Groups
public Class Entity2 : Base
{
public int layerId;
}
These entities are filled as an input from UI using Json, I need to pass them to a processing method, which gives the same Output entity. Method has a logic to handle if List<int> Groups is null, I need to create a method which is capable of handling each of the input in an elegant manner. I cannot just use only Entity1, since they are two different functional inputs for different business process, so using Entity1 as direct replacement would be a mis-representation
Instead of creating overload of the function, I can think of following options:
Use object type as input and typecast in the function internally
I think we can similarly use dynamic types, but solution will be similar as above, it will not be a clean solution in either case, along with the switch-case mess.
What I am currently doing is processing method is like this:
public OuputEntity ProcessMethod(Entity 1)
{
// Data Processing
}
I have created a constructor of Entity1, that takes Entity2 as Input.
Any suggestion to create an elegant solution, which can have multiple such entities. May be using generic, where we use a Func delegate to create a common type out of two or more entities, which is almost similar to what I have currently done. Something like:
Func<T,Entity1>
Thus use Entity1 output for further processing in the logic.
I need to create a method which is capable of handling each of the input in an elegant manner
Create an Interface, or a contract so to speak, where each entity adheres to the particular design. That way common functionality can be processed in a similar manner. Subsequently each difference is expressed in other interfaces and testing for that interface sis done and the differences handled as such.
May be using generic,
Generic types can be tested against interfaces and a clean method of operations hence follows suit.
For example say we have two entities that both have Name properties as string, but one has an Order property. So we define the common interface
public interface IName
{
string Name { get; set; }
string FullName { get; }
}
public interface IOrder
{
decimal Amount { get; set; }
}
So once we have our two entities of EntityName and EntityOrder we can add the interfaces to them, usually using the Partial class definition such as when EF creates them on the fly:
public partial class EntityName : IName
{
// Nothing to do EntityName already defines public string Name { get; set; }
public string FullName { get { return "Person: " + Name; }}
}
public partial class EntityOrder : IName, IOrder
{
// Nothing to do Entity Order already defines public string Name { get; set; }
// and Amount.
public string FullName { get { return "Order: " + Name; } }
}
Then we can process each of them together in the same method
public void Process(IName entity)
{
LogOperation( entity.FullName );
// If we have an order process it uniquely
var order = entity as IOrder;
if (order != null)
{
LogOperation( "Order: " + order.Amount.ToString() );
}
}
Generic methods can enforce an interface(s) such as:
public void Process<T>(T entity) where T : IName
{
// Same as before but we are ensured that only elements of IName
// are used as enforced by the compiler.
}
Just create generic method that will do this work for you:
List<OuputEntity> MyMethod<T>(T value) where T : Base
// adding this constraint ensures that T is of type that is derived from Base type
{
List<OutputEntity> result = new List<OutputEntity>();
// some processing logic here like ...
return result;
}
var resultForEntity1 = MyMethod<Entity1>();
var resultForEntity2 = MyMethod<Entity2>();
P.S. check my answer for this question as you may find it useful too:
map string to entity for using with generic method
You probably want to implement an interface or an abstract class.
From MSDN
If you anticipate creating multiple versions of your component, create
an abstract class. Abstract classes provide a simple and easy way to
version your components. By updating the base class, all inheriting
classes are automatically updated with the change. Interfaces, on the
other hand, cannot be changed once created. If a new version of an
interface is required, you must create a whole new interface.
If the functionality you are creating will be useful across a wide range of
disparate objects, use an interface. Abstract classes should be used
primarily for objects that are closely related, whereas interfaces are
best suited for providing common functionality to unrelated classes.
If you are designing small, concise bits of functionality, use
interfaces. If you are designing large functional units, use an
abstract class.
If you want to provide common, implemented
functionality among all implementations of your component, use an
abstract class. Abstract classes allow you to partially implement your
class, whereas interfaces contain no implementation for any members.
Abstract Class Example
Cat and Dog can both inherit from abstract class Animal, and this abstract base class will implement a method void Breathe() which all animals will thus do in exactly the same fashion. (You might make this method virtual so that you can override it for certain animals, like Fish, which does not breath the same as most animals).
Interface Example
All animals can be fed, so you'll create an interface called IFeedable and have Animal implement that. Only Dog and Horse are nice enough though to implement ILikeable - You'll not implement this on the base class, since this does not apply to Cat.

Generics and inheritance... Getting around having to specify the <T> type?

Well, I've had to rewrite this as I've been down voted five times for giving too much detail... Go figure!
class BaseModel
{
public T[] Get<T>()
{
// return array of T's
}
public T Find<T>(object param)
{
// return T based on param
}
public T New<T>()
{
// return a new instance of T
}
}
class BaseRow
{
private BaseModel _model;
public BaseRow(SqlDataReader rdr, BaseModel model)
{
// populate properties of inheriting type using rdr column values
}
public void Save()
{
// calls _model.Save(this);
}
}
I currently have a number of classes that inherit the BaseModel class. Each of the methods exposed by BaseModel will return an instance, or an array of instances of a type that inherits the BaseRow class.
At the moment, when calling the exposed methods on the BaseModel via an inheriting class, i.e.
using(DeviceModel model = new DeviceModel())
{
DeviceRow row = model.Find<DeviceRow>(1);
DeviceRow[] rows = model.Get<DeviceRow>();
DeviceRow newRow = model.New<DeviceRow>();
}
I have to specify the type (a class that inherits the BaseRow class), as the methods in BaseModel/BaseRow do not know/care what type they are, other than they inherit from BaseRow.
What I would like to do is find a way to remove the need to specify the without having to replicate code in every class that inherits BaseModel, i.e.
class DeviceModel : BaseModel
{
public DeviceRow Find(object param)
{
return this.Find<DeviceRow>(param);
}
}
Note: Unfortunately I am unable to implement or use any third party solutions. That said, I have tried using Castle Active Record/nHibernate and to be honest, they are very big and heavy for what should be a very simple system.
Hopefully I haven't provided "too much" detail. If I have, please let me know.
Thanks
If I were you, I'd suggest making BaseModel a generic class. In a situation of "can't win either way", the code you've removed to make others happy might have told me more about what you're doing (not a criticism by any stretch - I appreciate your position).
class BaseModel<T>
{
public virtual T[] Get()
{
// return array of T's
}
public virtual T Find(object param)
{
// return T based on param
}
public virtual T New()
{
// return a new instance of T
}
}
That's your base, and then you have inheritors like:
class DeviceModel : BaseModel<Device>
{
public override Device New()
{
return new Device();
}
}
Now, any generic operations you define in DeviceModel will default to returning or using strongly typed Device. Notice the virtual methods in the BaseModel class. In the base class methods, you might provide some basic operations predicated upon using T's or something. In sub-classes, you can define more specific, strongly typed behavior.
I'd also comment that you might want to pull back a little and consider the relationship of BaseModel and BaseRow. It appears that you're defining a parallel inheritance hierarchy, which can tend to be a code smell (this is where more of your code might have come in handy -- I could be wrong about how you're using this). If your ongoing development prospects are that you're going to need to add a FooRow every time you add a FooModel, that's often a bad sign.

Constructor injection with non-dependency parameters

I have an interface ITradingApi like so:
public interface ITradingApi
{
IOrder CreateOrder(...);
IEnumerable<Symbol> GetAllSymbols();
// ...
}
This is meant to be a facade for the different APIs of the vendors of trading software.
My view model has a dependency on this trading API in its constructor:
public class MainViewModel
{
public MainViewModel(ITradingApi tradingApi) { /* ... */ }
// ...
}
I use Ninject as an IoC container, so I will create an instance of my view model like this:
var vm = kernel.Get<MainViewModel>();
Now, my problem:
The implementation of ITradingApi might need additional parameters to work.
Example:
One vendors API uses TCP/IP internally, so I need a hostname and a port.
Another vendor uses a COM object. Here I don't need any info.
A third vendor needs username and password of the account.
In the spirit of not allowing incomplete objects, I added these as parameters to the constructors of the concrete implementations.
Now, I am not sure, how this would work. Clearly, these additional parameters do not belong into the interface, because they are specific to each implementation.
On the other hand, these additional parameters need to be entered by the end-user and then passed to the implementation of ITradingApi, meaning that the user of ITradingApi needs intimate knowledge about the concrete implementation.
How to solve this dilemma?
UPDATE:
One approach could be to create an ITradingApiProvider that exposes a list of required parameters. The View could automatically create an input form for these parameters that is databound to the parameters in ITradingApiProvider. Now, when an ITradingApi instance is requested from the provider, it can make use of these parameters to create an instance of the concrete implementation. Clearly the implementation of ITradingApiProvider and ITradingApi are tightly coupled, but I think that is not a problem as long as each implementation of ITradingApi comes with a corresponding implementation of ITradingApiProvider.
Based on the information so far put forth here, I'd like to point out one or two things:
First of all, whether or not the concrete configuration values are supplied at composition time or truly first available at runtime as user input makes a huge difference. As long as they can be resolved at composition time things are easy because you can simply read the values from the environment and supply them to the appropriate constructors. So, for the rest of this answer I'm going to assume that things are much harder and you actually need to get those values from the user at runtime.
Instead of attempting to come up with a general-purpose configuration API I'd much rather model what's actually going on. In this case it sounds to me like we're collecting configuration values from the user, so why not model this explicitly?
Product Trader
Define an interface like this:
public interface ITradingApiTrader
{
ITradingApi Create(Type apiType);
}
Here, it's assumed that apiType can cast to ITradingApi, but this can't be enforced by the compiler. (The reason I'm calling this a 'Trader' is because this is a variation of the Product Trader pattern (PLoPD 3).)
How is this different than before?
Well, you can implement the Create method by showing a user interface for each type of ITradingApi. Each concrete user interface gathers the values required for its own concrete ITradingApi implementation and subsequently returns a correctly configured instance.
If you know the concrete types at compile time, other variations include these:
public interface ITradingApiTrader
{
ITradingApi CreateMT4TradingApi();
ITradingApi CreateFooTradingApi();
ITradingApi CreateBarTradingApi();
// etc.
}
Perhaps you can also do this (although I haven't tried to compile this):
public interface ITradingApiTrader
{
ITradingApi Create<T>() where T : ITradingApi;
}
Note also that you don't need to define the first ITradingApiTrader's Create method based on a Type - any identifier (such as an enum or string) might do instead.
Visitor
If the set of ITradingApi is (finite and) known at design time, the Visitor design pattern might also offer an alternative.
If you use a Visitor, you can make the Visit method show an appropriate user interface and then subsequently use the values collected from the user interface to create the appropriate ITradingApi instance.
Basically this is just a variation on the previous 'solution' where the Product Trader is implemented as a Visitor.
Is this what your after?
ninjectKernel.Get<MainViewModel>().WithConstructorArgument("tradingApi",
kernel.Get<ITaxCalculator>() .WithConstructorArgument("additionalParameter","someValue")));
Ok my two cents, I am not sure of anything you know. It is just to help and try...
We give a visitor to your api as construction of the interface:
public interface ITradingApi
{
Object CreateOrder();
IEnumerable<Object> GetAllSymbols();
}
public class TradingApi : ITradingApi
{
IvisitorAPI _VisitorAPI;
public TradingApi(IvisitorAPI visitorAPI)
{
_VisitorAPI = visitorAPI;
}
public Object CreateOrder()
{
var Order = new Object();
//bla bla bla
//here code relative to different visitor
_VisitorAPI.SaveOrder(Order);
return Order;
}
}
It is your visitor that knows how to handle some of the action, because depending on the visitor he will use your api in different ways to achieve the same action ( here SaveOrder).
public interface IvisitorAPI
{
bool SaveOrder(Object order);
}
public class visitorApiIP : IvisitorAPI
{
public string HostName { get; set; }
public int Port { get; set; }
public visitorApiIP(string hostname, int port)
{
HostName = hostname;
Port = port;
}
public bool SaveOrder(Object order)
{
//save the order using hostname and ip
//...
//....
return true;
}
}
Only the visitor has a knowledge of what he needs to achieve his version of the action.
Therefore it is not the APi that needs additionnal parameters, we are pushing the logic away in the visitor class.
This visitor class might be created only when ewe know who is the visitor therefore, surely at runtime
Hope it might give you some perspective. I do not know if the whole theory can be applied your exact situation.
My best anyway ;)
The solution is to use the approach as outlined in the update part of my question. ITradingApiProvider takes the role of an abstract factory and thus should be renamed to ITradingApiFactory. It would expose a list of needed parameters whose values can be set. This list in turn can be used by the View to automatically present the user with an input form to enter a value for each parameter, because only the user knows the values of for the parameters.
The call to Create would then use these parameters:
public interface ITradingApiFactory
{
ITradingApi Create();
IEnumerable<Parameter> Parameters { get; }
}
public class Parameter
{
public Parameter(Type type, string name, string description)
{ Type = type; Name = name; Description = description; }
public Type Type { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public object Value { get; set; }
}
public class MT4TradingApiFactory : ITradingApiFactory
{
Dictionary<string, Parameter> _parameters;
public MT4TradingApiFactory()
{ /* init _parameters */ }
public ITradingApi Create()
{
return new MT4TradingApi(_parameters["hostname"].ToString(),
(int)_parameters["port"]);
}
IEnumerable<Parameter> Parameters { get { return _parameters.Values; } }
}
More info can be found in this answer.
This can be advanced further to make it easier to use, by giving each Factory implementation the parameters as properties and change the Parameter class to work directly on these properties using expression trees. If someone is interested in this advanced factory design, please leave a comment.
I think there is nothing wrong with your provider approach. You have two concerns here:
An operational one: your ITradingAPI which defines a contract for operations you can perform.
A meta-data one: something which describes properties of an actual implementation (meta data might not be quiet right but can't think of a better name for it)
Now apparently you need something which can make the connection between the two and that is your ITradingAPIProvider. Seems reasonable straight forward and has good chance of that you will still understand your code when coming back to it after a year ot two ;)
How about trying something similar to the strategy pattern? Create a new interface called IConnectStrategy:
interface IConnectStrategy
{
void Connect();
}
Add the connectstrategy as an argument to the method void CreateOrder(IConnectStrategy connectStrategy) in ITradingApi and let each vendor create/specify their own method for connecting. E.g. for one vendor create:
public class TCPConnectStrategy : IConnectStrategy
{
public TCPConnectStrategy(string hostName, int port)
{
/* ... */
}
public void Connect()
{
/* ... tcp connect ... */
}
}
(Connect might not be the best name or even what you are actually doing, but please apply it to whatever works for your project.)
Edit after comments:
Create a strategy that only have contracts for each method that have vendor-specific parameters. Then add a method void SetVendorStrategy(IVendorStrategy vendorStrategy) (or a property) to the ITradingAPI-interface. Each implementation of the strategy has their own constructor with their own parameters, and each method (that require vendor specific parameters) in each implementation of the ITradingAPI-interface simply calls vendorStrategy.DoSomethingWithVendorSpecificData().

Is there a way to apply c# generic constraints severally rather than jointly?

Is there a way to apply several different csharp generic constraints to the same type where the test is OR rather than AND?
I have an extension method I want to apply to a subset of an interface, but there is no common interface or base class that only captures the classes I wish to target.
In the example below, I could write multiple methods each with a single constraint that all call the same Swim method, but I am wondering if there is a way to write one method with multiple non-intersecting constraints.
Eg
interface IAnimal
{
bool IsWet { get; set; }
bool IsDrowned { get; set; }
}
public static class SwimmingHelpers
{
/*this is the psuedo effect of what I would like to achieve*/
public static void Swim<T>(this T animalThatCanSwim)
where T: IAnimal, Human |
where T: IAnimal, Fish |
where T: IAnimal, Whale ....
}
FYI The actual scenario I am toying with is HTML elements that all implement an IElement interface but I want to target only elements where certain behaviours are valid in the HTML specification and no more specific common interface is implemented by them eg: elements that can have a readonly attribute.
Not with generics. You could, however, get what you want by defining plain overloads like this:
public static class SwimmingHelpers {
public static void Swim(this Human animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
public static void Swim(this Fish animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
public static void Swim(this Whale animalThatCanSwim) {
SwimInternal(animalThatCanSwim);
}
private static void SwimInternal(IAnimal animalThatCanSwim) {
// do your work here, no duplication of the code needed
}
}
The reason it doesn't work that way makes sense when you consider the fact that generic constraints aren't there to enforce your intended use of the method. Rather, they are there to allow you to make certain assumptions about the type parameter. For example, by constraining the type to be IComparable, you know that you can call a Compare method even though the exact type is not known yet. Constraining a type with new() ensures that you can call a default constructor on the type. So if generic constraints allowed you to specify one constraint or another, you could not make those assumptions.
There is no OR operator in generics.
But you can always introduce new interface to capture the subset of classes, ie. IReadOnly. This can be a marker interface that doesn't define any methods. Over time you might actually to find some usage for those new interfaces...

How can I implement an interface that can take many object types

excuse what seems like a real noobie question but how can I implement the following
public interface IViewModel {
void Map<T>();
}
public class CarViewModel : IViewModel
{
public string Color { get; private set; }
public int Tyres { get; private set; }
public CarViewModel(Car _car)
}
//this is where the problem is - there can be many differnt kind of object but I want them all to implement a Map function. I want to be able to assign the properties to incoming object. I also need to cater for IList of cars coming in that need to be populated. I suspect I am not using Generics properly
public void Map<T>(Car _car){
Color = _car.Color;
Tyres = _car.Tyres;
}
Do you mean this?
public interface IViewModel<T>
{
void Map(T domainObject);
}
public class CarViewModel : IViewModel<Car>
{
public Map(Car domainObject) { ... }
}
You say:
I suspect I am not using Generics properly
and you are correct. Additionally, you are not using polymorphism properly.
If you want to polymorphically accept several different types that all have something in common, then you need to create an interface that is the parent type of all of the types you will be using. You can do this without using any Generics at all.
What Generics (aka parametric polymorphism) gives you is a way to create one type that is parameterized by another type (and thus behaves like many different types). For example, IList<T> is parameterized by a type variable T -- then IList<string> and IList<int> are two separate types (with many possible subtypes each), but you only have to write the code once.
What are your actual requirements for this design? What are your ViewModel classes trying to accomplish?

Categories

Resources