我试图找到一种方法来改进我的一些代码。我使用第三方API,它有一个非常复杂的API请求对象(我称之为ScrewyAPIObject),其中有大量的重复。每次要设置特定属性时,都可能需要一页代码。所以我构建了一个库来提供一个简化的包装器来设置/获取它的属性(并处理一些值预处理)。
以下是关于其运作方式的精简视图:
public abstract class LessScrewyWrapper
{
protected ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
public void Set(string value)
{
Set(_getPropertyName(), value);
}
public void Set(string property, string value)
{
// Preprocess value and set the appropriate property on _screwy. This part
// has tons of code, but we'll just say it looks like this:
_screwy.Fields[property] = "[" + value + "]";
}
protected string _getPropertyName()
{
// This method looks at the Environment.StackTrace, finds the correct set_ or
// get_ method call and extracts the property name and returns it.
}
public string Get()
{
// Get the property name being access
string property = _getPropertyName();
// Search _screwy's structure for the value and return it. Again, tons of code,
// so let's just say it looks like this:
return _screwy.Fields[property];
}
public ScrewyAPIRequest GetRequest()
{
return _screwy;
}
}
然后我有一个子类,代表一个特定类型的棘手的API请求(有多种类型都具有相同的结构,但设置不同)。我们只说这个有两个字符串属性,PropertyA和PropertyB:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA
{
get { return Get(); }
set { Set(value); }
}
public string PropertyB
{
get { return Get(); }
set { Set(value); }
}
}
现在,当我想使用这个库时,我可以这样做:
SpecificScrewyAPIRequest foo = new SpecificScrewyAPIRequest();
foo.PropertyA = "Hello";
foo.PropertyB = "World";
ScrewyAPIRequest request = foo.GetRequest();
这很好用,但是有不同种类的数据类型,包括在我的Set / Get方法中使用泛型,当你处理50个属性时它只会使子类显得有点笨拙和50个Get()和Set()调用。
我喜欢做的只是定义字段,如下所示:
public class SpecificScrewyAPIRequest : LessScrewyWrapper
{
public string PropertyA;
public string PropertyB;
}
这会使课程看起来更清洁。问题在于,无论何时访问和修改字段的值,我都不知道如何让.NET对我的自定义处理程序进行回调。
我发现有人在PHP中使用__set和__get魔术方法做了类似的事情(尽管他们不打算使用它们),但我在C#中找不到类似的东西。有什么想法吗?
编辑:我考虑过对我的类使用索引方法,然后将对象类型值转换为适当的类型,但是我更喜欢保留定义属性的方法特定类型。
答案 0 :(得分:1)
也许在你的情况下DynamicObject
是一个合适的选择:
public class ScrewyDynamicWrapper : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// get your actual value based on the property name
Console.WriteLine("Get Property: {0}", binder.Name);
result = null;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// set your actual value based on the property name
Console.WriteLine("Set Property: {0} # Value: {2}", binder.Name, value);
return true;
}
}
定义你的包装器对象:
public class ScrewyWrapper
{
protected dynamic ActualWrapper = new ScrewyDynamicWrapper();
public int? PropertyA
{
get { return ActualWrapper.PropertyA; }
set { ActualWrapper.PropertyA = value; }
}
public string PropertyB
{
get { return ActualWrapper.PropertyB; }
set { ActualWrapper.PropertyB = value; }
}
}
但是,您不能依赖此ScrewyDynamicWrapper
中的属性类型,因此这取决于您的实际API要求 - 可能对您不起作用。
答案 1 :(得分:1)
而不是字段,如果在类中定义为属性,那将更容易。
classdef test_parser < matlab.mixin.Copyable & dynamicprops
properties (AbortSet = true)
a
end
end
function result = make_class(array)
result = test_parser;
result.a = array(1);
if length(array)>1
result.addprop('b')
result.b=array(2);
end
end
>> make_class([10])
ans =
test_parser with properties:
a: 10
>> make_class([10,20])
ans =
test_parser with properties:
a: 10
b: 20
然后,您可以创建扩展通用方法以返回public class SpecificScrewyAPIRequest
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
对象。
ScrewyAPIRequest
现在,您可以轻松地从任何类对象中获取public static class Extensions
{
public static ScrewyAPIRequest GetRequest<T>(this T obj)
{
ScrewyAPIRequest _screwy = new ScrewyAPIRequest();
var test= obj.GetType().GetProperties();
foreach (var prop in obj.GetType().GetProperties())
{
_screwy.Fields[prop.Name] = prop.GetValue(obj, null);
}
return _screwy;
}
}
。
您的代码如下所示。
ScrewyAPIRequest