I've been attempting to design a efficient interface that I'm using for some plugins. I thought I had found a decent interface but trying to implement it is not going well. So I was hoping to see if anyone out here has some better suggestions as to how this could be done. It errors out with "does not contain a public definition for 'GetEnumerator'"
Plugin interface:
namespace ALeRT.PluginFramework
{
public interface IQueryPlugin
{
string PluginCategory { get; }
string Name { get; }
string Version { get; }
string Author { get; }
System.Collections.Generic.List TypesAccepted { get; }
}
interface IQueryPluginRBool : IQueryPlugin
{
bool Result(string input, bool sensitive);
}
interface IQueryPluginRString : IQueryPlugin
{
string Result(string input, bool sensitive);
}
}
In essence I am attempting to take a list of types that should be used (types could be URL, Name, Email, IP, etc.) and compare them to the value in the query plugin. Each query plugin can possibly have multiple types it accepts. When they match, it performs the actions that are in the query plugin.
[ImportMany]
public IEnumerable<IQueryPlugin> QPlugins { get; set; }
private void QueryPlugins(List<string> val, bool sensitive)
{
foreach (string tType in val) //Cycle through a List<string>
{
foreach (var qPlugins in this.QPlugins) //Cycle through all query plugins
{
foreach (string qType in qPlugins) //Cycle though a List<string> within the IQueryPlugin interface AcceptedTypes
{
if (qType == tType) //Match the two List<strings>, one is the AcceptedTypes and the other is the one returned from ITypeQuery
{
//Do stuff here
}
}
}
}
}
Your code
foreach (string qType in qPlugins)
{
if (qType = tType)
{
//Do stuff here
}
}
Will not work. You must iterate through qPlugins.TypeAccepted
First of all. Do not expose a list (like the line below) since it violates Law Of Demeter. That means that the plugin do not how control over it's own list. Anyone that have a reference to the plugin can modify the list.
System.Collections.Generic.List TypesAccepted { get; }
This is better:
IEnumerable<TheType> TypesAccepted { get; }
But that still let's anyone modify the elements of the list (without the knowledge of the plugin). It's fine if the elements are immutable.
A better solution would be to create methods in the plugin interface. For instance have a visitor pattern method:
public interface IPluginTypeVisitor
{
void Visit(AcceptedType type);
}
public interface IQueryPlugin
{
string PluginCategory { get; }
string Name { get; }
string Version { get; }
string Author { get; }
void VisitTypes(IPluginTypeVisitor visitor);
}
But the best solution in the case of your loop example is simply:
public interface IQueryPlugin
{
string PluginCategory { get; }
string Name { get; }
string Version { get; }
string Author { get; }
bool IsTypeAcceptable(TheTypeType type); // get it, thetypetype? hahaha
}
private void QueryPlugins(List<string> val, bool sensitive)
{
foreach (string tType in val) //Cycle through a List<string>
{
foreach (var plugin in this.QPlugins) //Cycle through all query plugins
{
if (plugin.IsTypeAcceptable(tType))
//process it here
}
}
}
Related
I recently came across a piece of code at work that has a repeating if-else condition that checks on an enum called OperationType :
public enum OperationType
{ A, B }
Right now the class's job is to run an operation either on device A or on device B, while reading from a SharedDevice and store some values basically for an X,Y plot. We record the characteristics of the SharedDevice in the function of DeviceA or DeviceB. The problem is that we need to iterate over a list of different parameters and send them to the SharedDevice. This list is different for device A and for device B.
Device class:
public class Device
{
public double CurrentValue { get; }
public DeviceParameters Parameters { get; set; }
}
And here is the class responsible for executing this operation:
public class MyOperationExecuter
{
public Device SharedDevice { get; }
public Device DeviceA { get; }
public Device DeviceB { get; }
public List<DeviceParameters> ParametersA { get; }
public List<DeviceParameters> ParametersB { get; }
public List<double> XValuesOfA { get; }
public List<double> YValuesOfA { get; }
public List<double> XValuesOfB { get; }
public List<double> YValuesOfB { get; }
public void DoMyOperation(OperationType operationType)
{
List<DeviceParameters> changingDeviceParameters;
if (operationType == OperationType.A)
{
changingDeviceParameters = ParametersA;
}
else
{
changingDeviceParameters = ParametersB;
}
if (operationType == OperationType.A)
{
XValuesOfA.Clear();
YValuesOfA.Clear();
}
else
{
XValuesOfB.Clear();
YValuesOfB.Clear();
}
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
if (operationType == OperationType.A)
{
XValuesOfA.Add(DeviceA.CurrentValue);
YValuesOfA.Add(SharedDevice.CurrentValue));
}
else
{
XValuesOfB.Add(DeviceB.CurrentValue);
YValuesOfB.Add(SharedDevice.CurrentValue);
}
}
// save updated x,y data
Save();
}
}
As you can see there is a repeating if statement which is not very future proof, since we have to check for the enum in every single step. Also we might need to add an C-type device which would result in an ever growing switch statement. We might also need to execute operations on both A and B. How should I refactor this operation so I can keep extending it without this always repeating if-else logic?
A fairly simple way would be to declare a variable representing A or B:
var XValues = operationType == OperationType.A ? XValuesOfA : XValuesOfB;
then you can just use XValues. Do the same for DeviceA. If you have more operations you could use a switch expression.
A neater solution would be to make separate objects containing everything needed for A or B, so your class could simply check the operation type and then delegate all the work to respective object. I.e.
public class MyDevice
{
public Device SharedDevice { get; }
public Device Device { get; }
public List<DeviceParameters> Parameters { get; }
public List<double> XValuesOf { get; }
public List<double> YValuesOf { get; }
public void DoMyOperation()
{
...
}
}
I would also recommend using a single list containing both X and Y values, something like a Vector2. I find this easier to use, and helps avoid repeating code.
Without changing class fields/properties I'd go with new method:
private void SetParameters(List<DeviceParameters> parameters, List<double> xValues, List<double> yValues, Device device)
{
xValues.Clear();
yValues.Clear();
foreach(var parameter in parameters)
{
SharedDevice.Parameters = parameter;
xValues.Add(device.CurrentValue);
yValues.Add(SharedDevice.CurrentValue);
}
}
And then in DoMyOperation it's enough to:
if (operationType == OperationType.A)
{
SetParameter(ParametersA, XValuesOfA, YValuesOfA, DeviceA);
}
else
{
SetParameter(ParametersB, XValuesOfB, YValuesOfB, DeviceB);
}
You should add new class. Which will be used to define device type specific properties.
A class like this;
public class MyDeviceValues
{
public MyDeviceValues(List<DeviceParameters> parameters, List<double> xValuesOf, List<double> yValuesOf)
{
Parameters = parameters;
XValues = xValuesOf;
YValues = yValuesOf;
}
public List<DeviceParameters> Parameters { get; }
public List<double> XValues { get; }
public List<double> YValues { get; }
}
So, you can have a generic DoMyOperation function. It will be like this:
public void DoMyOperation(MyDeviceValues myDeviceValues)
{
var changingDeviceParameters = myDeviceValues.Parameters;
myDeviceValues.XValues.Clear();
myDeviceValues.YValues.Clear();
foreach (var parameters in changingDeviceParameters)
{
// set the device parameters
SharedDevice.Parameters = parameters;
// retrieve the device readings and store the values in the correct dataprovider
myDeviceValues.XValues.Add(DeviceA.CurrentValue);
myDeviceValues.YValues.Add(SharedDevice.CurrentValue);
}
// save updated x,y data
Save();
}
Here is the refactored version of the whole code you pasted:
https://dotnetfiddle.net/dLyJl9
With the help of everyone in a very short time. The problem got solved by overriding the toString Method.
I have a problem with the following: (solved)
public class CryptoApiResponse
{
[DeserializeAs(Name = "ticker")]
public List<CryptoAttributes> CryptoCurrency { get; set; }
public override string ToString()
{
return $"Currency:{CryptoCurrency[0].Currency} " +
$"PriceFiat:{CryptoCurrency[0].PriceFiat} " +
$"Fiat:{CryptoCurrency[0].TargetFiat}";
}
}
public class CryptoAttributes
{
[DeserializeAs(Name = "base")]
public string Currency { get; set; }
[DeserializeAs(Name = "target")]
public string TargetFiat { get; set; }
[DeserializeAs(Name = "price")]
public string PriceFiat { get; set; }
}
And I want to access the following:
public void Display<CryptoApiResponse>(List<CryptoApiResponse> apiList)
{
if (apiList != null)
{
foreach (CryptoApiResponse cryptoCurrency in apiList)
{
Console.WriteLine(cryptoCurrency.ToString());
}
}
Console.ReadLine();
}
Console.WriteLine(obj);
// this means more or less the following
Console.WriteLine(obj.ToString());
// this means you should override the ToString() method
// or to make a custom string
You're iterating through a List, and in each crypto there exist a sub-list List. In short you get List>.
When you foreach this List, you may need to use a second foreach to iterate the values in the Sub list to reach your property.
foreach (var crypt in crypto)
{
foreach (var basedata in crypt.Ticker)
{
Console.WriteLine($"Currency:{basedata.Currency} Price: {basedata.Price} Target: {basedata.Target}");
}
}
If you keep the naming of the API you linked and differentiate between lists ans single objects names it will be easier to understand what is the problem. The classes should look something like this (pay attention to the difference between Ticker and Tickers
public class Crypto
{
public List<Ticker> Tickers { get; set; }
}
public class Ticker
{
public string Currency { get; set; }
public string Target { get; set; }
public string Price { get; set; }
}
The parameter crypto (should be cryptos) in Display is a list and Tickers is a list, so you need nested loop. You should also remove the Crypto parameter from the methos signature as it hides the Crypto class
public void Display(List<Crypto> cryptos)
{
foreach (Crypto crypto in cryptos)
{
foreach (Ticker ticker in crypto.Tickers)
{
Console.WriteLine(ticker);
}
}
}
Or if you would like to use partial Linq
public void Display(List<Crypto> cryptos)
{
foreach (Ticker ticker in cryptos.SelectMany(crypto => crypto.Tickers))
{
Console.WriteLine(ticker);
}
}
Could you try to use "Crypto" instead of "var" when looping? I mean do it like this. I remeber the version before VS2015 (may be VS2010), the type of variable will be treated as object if we use "var".
public void Display<Crypto>(List<Crypto> crypto)
{
if (crypto != null)
{
// Currency, Target and Price
foreach (***Crypto*** ticker in crypto)
{
Console.WriteLine(ticker); // ticker Type Crypo
// ticker.Ticker
}
}
Console.ReadLine();
}
Whats happening right now : i have class service and i have 5 propertys on it:
public class Service
{
public string prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
public string prop4 { get; set; }
public string prop5 { get; set; }
}
the sme class contains 100 methods where all of them want to change this properties, how can i decouple those methods in separate classes/services, so they still can change propertys?
Are there any other ways than usign reference of those propertys as parameters in methods?
UPDATE
So here is a service class:
public class Service
{
public string prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
public void ChangePropertyInOtherWay()
{
prop3 = "some random string";
}
public void ChangeProperty()
{
prop1 = "12";
}
public void ChangePropertyInSpecialWay()
{
prop2 = "monkey";
}
}
and the executer which handles execution of the functions.
public class Executer
{
private readonly Service _serv;
private readonly Dictionary<string, Action> functionlist;
public Executer(Service serv)
{
_serv = serv;
functionlist = new Dictionary<string, Action>();
functionlist.Add("ChangePropertyInOtherWay", () => serv.ChangePropertyInOtherWay());
functionlist.Add("ChangePropertyInOtherWay", () => serv.ChangePropertyInOtherWay());
functionlist.Add("ChangePropertyInSpecialWay", () => serv.ChangePropertyInSpecialWay());
}
public void ExecuteFunction(string functionName)
{
//INVOKE ONE of the function from the list
}
}
What i want to achieve is to decouple Service from Executer, so in executer i wouldnt need a reference to Service.
This may not be the best way but its how i would do it...
class Program
{
void Run()
{
DataGroup WorkingData = new DataGroup();
Modify("Put This string in here",new FooMethod(),"prop1",WorkingData);
Modify("This wont do anything", new BarMethod(), "prop5", WorkingData);
}
public void Modify(String Input, InterfaceWithData MethodUsed, String Property, DataGroup Data)
{
MethodUsed.FooFunction(Input, Property, Data);
}
}
interface InterfaceWithData
{
void FooFunction(String Input, String Property, DataGroup Data);
}
public class DataGroup
{
public string prop1 { get; set; }
public string prop2 { get; set; }
public string prop3 { get; set; }
public string prop4 { get; set; }
public string prop5 { get; set; }
}
public class FooMethod :InterfaceWithData
{
public void FooFunction(String Input, String Property ,DataGroup Data)
{
switch (Property)
{
case "prop1":
Data.prop1 = Input;
break;
case "prop2":
Data.prop2 = Input;
break;
case "prop3":
Data.prop1 = Input;
break;
case "prop4":
Data.prop3 = Input;
break;
case "prop5":
Data.prop5 = Input;
break;
default :
throw new System.ArgumentOutOfRangeException("Didnt chose a valid case");
}
}
}
public class BarMethod:InterfaceWithData
{
public void FooFunction(String Input, String Property, DataGroup Data)
{
Data.prop2 = "Monkey";
/*Do Something else with the data*/
}
}
This way once it is set up you can add as many methods as you like as long as you keep the syntax the same as is specified by the interface.
I am not sure why you are trying to do what you're trying to do in that way. Maybe if you can describe the overall problem you are having, instead of asking for a specific solution? Sometimes, that leads to better results (there may be much better ways of solving the overall problem than what you are proposing).
It seems a bit "funky" to be honest.
That said, if you want to continue with the approach for some reason, I recommend Reflection in combination with the nameof expression in C# 6.0 (if performance is not an issue).
Here's an example:
Foo.cs
public class Foo {
public string MyProperty { get; set; }
public void ChangePropertyInSomeWay() { ... }
}
Then in your Executer, you can do something like:
functionlist.Add(nameof(Foo.ChangePropertyInSomeWay));
And to invoke it when you have a function name, see this question.
With the above method, your code is actually decoupled (sure, your compiler still needs to know about Foo, but the compiled end result is a string). In the case that your compiler doesn't know about Foo, consider defining some interface that you refer in both the project where the Executer and the Service class is, and then get the name via that.
If you are trying to use strings to decouple parts of your code, then there most likely is a better way, and the above should be seen as a "last resort". Please update your questions with details on why you are doing what you are doing, and for what reason. Then we might be able to solve the problem in new ways.
It don't sound like something that should be possible, but I'd like to ask prior to writing it off.
I am writing an app with a plugin system, I would like to get the properties contained inside the plugin class prior to initializing or constructing it
Interface:
public interface IMPlugin
{
string PluginName { get; }
string PluginSafeName { get; }
string PluginDescription { get; }
Version PluginVersion { get; }
string PluginAuthorName { get; }
[DefaultValue(null)]
string PluginAuthorEmail { get; }
[DefaultValue(null)]
string PluginAuthorURL { get; }
[DefaultValue(false)]
bool PluginActive { get; set; }
/// <summary>
/// Plugin ID issued by InputMapper. Used for updates. </summary>
int PluginID { get; }
}
Plugin:
public class InputMonitor : IMPlugin,ApplicationPlugin
{
public string PluginName { get { return "My Plugin"; } }
public string PluginSafeName { get { return "MyPlugin"; } }
public string PluginDescription { get { return "My Plugin."; } }
public Version PluginVersion { get { return new Version("0.1.0.0"); } }
public string PluginAuthorName { get { return "John Doe"; } }
public string PluginAuthorEmail { get { return "foo#bar.com"; } }
public string PluginAuthorURL { get { return ""; } }
public int PluginID { get { return 0; } }
public bool PluginActive { get; set; }
public InputMonitor()
{
}
}
My issue is I want my application to be able to retrieve the plugin info prior to initializing it so users can activate and deactivate plugins at will but the details of the plugin still be visible in a plugin browser. But I don't want to have to rely on the plugin developers to not do anything in their constructor and only put their code in other interfaced methods.
Can a object be initialized and forcibly have its constructor ignored, or is there something to disallow constructors all together?
It sounds like your plugins should be configured via attributes rather than via exposing properties:
[Plugin(Name = "My Plugin", SafeName = "MyPlugin" ...)]
public class InputMonitor
You can access the attributes via reflection without creating an instance of the class.
After all, this is metadata about the type - not information about any one instance of the type.
Initializing a class and calling its constructor is the same thing.
Either you construct an instance of your plugin class just to read its properties and throw it away afterwards.
Or
You have a second helper/describer class. (which I understood you don't want)
I'm trying to accomplish some hacking & slashing and was wondering how to approach the following.
There are 2 interfaces defined:
public interface IBase
{
string Name { get; }
void Run();
}
public interface ISecondBase<T> : IEntityTask
{
Thing<T> Thing { get; }
}
Somewhere else I have a list of IBase.
This list is filled ISecondBase. I would like to be able to loop through the list of Base, but using some reflection tricks and hacks als be able to call Thing on the items. I know they're there, the compiler doesn't.
So I'd have to cast it to its concrete type at runtime, but this cast has to be dynamic, based on reflected information in the loop... So all type information is dynamic... I'm starting to think in circles :)
Since I know on beforehand that everything inside it is always of the SecondBase type, I decided to use the dynamic keyword and just let it resolve at runtime. This seems to me like an easy way out. Is there some best practice for these cases? Should I redesign, without loss of generality, and how?
foreach(var x in y)
{
dynamic melp = x;
melp.Thingy;
}
Where to start?
Edit: Perhaps some more code to make the example less contrived.
I have the base classes as mentioned. In real life they look like this:
public interface IEntityTask
{
string Name { get; }
void Run();
}
public interface IEntityTask<T> : IEntityTask
{
Task<T> Task { get; }
}
//Then there are classes that implement these:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
public T Entity { get; private set; }
public Func<T, Guid> EntityMethod { get; private set; }
public Task<Guid> Task { get; private set; }
public void Run()
{
Task = Task<Guid>.Run(() => entityAccess.CreateEntity<T>(Entity, EntityMethod));
}
}
public class ReadEntityTask<T> : IEntityTask<T>
{
public Guid EntityId { get; private set; }
public Func<Guid, T> EntityMethod { get; private set; }
public Task<T> Task { get; private set; }
public void Run()
{
Task = Task<T>.Run(() => entityAccess.ReadEntity<T>(EntityId, EntityMethod));
}
}
//Furthermore there is a class called EntityTaskManager, which holds a list of these things and runs, awaits & collects the results on them.
public class EntityTaskManager
{
public List<IEntityTask> EntityTasks { get; set; } // I want tasks of Guid and bool in here!!!!
public Dictionary<string, object> EntityTaskResults { get; set; }
}
In a calling class I construct a new EntityTask and add it to the list. And then call RunTasks on the manager.
I'd modify IEntityTask like this:
public interface IEntityTask
{
string Name { get; }
void Run();
object Result { get; }
}
If EntityTaskManager is the only place, where you work with IEntityTask type, the implementation of Result would be explicit:
public class CreateEntityTask<T> : IEntityTask<Guid>
{
/* The rest of code here */
object IEntityTask.Result
{
get { return Task.Result; }
}
}
Then fetching task results should be trivial:
var results = entityTasksManager
.EntityTasks
.Select(t => t.Result);