简体   繁体   English

方法参数(对象)不是类型列表C#

[英]Method Parameter (Object) not of Type List C#

Hi there I have looked and need some help, I am using reflections to get values from a class, The classes have a similar property called "Name" I have a method 嗨,我已经看过并需要一些帮助,我正在使用反射从类中获取值,这些类具有一个类似的名为“ Name”的属性,我有一个方法

public static void GetName<T>(T Object)
{
    xxxxxxx
}

Now the user will use this method with someting like so 现在,用户将使用这种方法,像这样

var User = .....
var name = GetName(User);

How can I restrict usage to a class object only, as I want to prevent List and other types from being use ex 我要如何限制使用仅限于类对象,因为我想防止List和其他类型被使用

List<SystemUsers> users = ..... 
var name = GetName(users) ... this should not be allowable

Is there such a way, I tried placing "class" and "where T : new()" 有没有这种方法,我尝试放置“类”和“哪里T:new()”

But it does not seem it is doing the trick 但似乎并没有解决问题

Please Help 请帮忙

In your GetName() method, you will need to test the object type, and throw an exception if it is not a valid type. 在您的GetName()方法中,您将需要测试对象类型,如果不是有效类型,则引发异常。

However, this really isn't an efficient way of doing this. 但是,这确实不是一种有效的方法。 You might be better using an interface instead, so that you won't need to worry with what types you don't allow--since the number of invalid types could reach infinite limits. 您最好改用接口,这样您就不必担心不允许的类型,因为无效类型的数量可以达到无限的限制。

正如Daniel在对原始问题的评论中所指出的那样,让每个对象实现一个包含该属性的接口,并让您的方法将该接口作为其参数,这是限制它的最佳方法,例如:

public static void GetName(IPerson entity) { entity.Name = "Test"; }

Just to throw another option out there, since you're already using reflection, you could also use it on the passed-in object to detect if it has a name property. 只是在这里抛出另一个选项,因为您已经在使用反射,所以也可以在传入的对象上使用它来检测它是否具有name属性。

This won't give any compile-time exceptions, however, so you'd have to try/catch when calling it or have it return an empty string instead of throw an exception (or something else...). 但是,这不会提供任何编译时异常,因此您必须在调用它时尝试/捕获它,或者让它返回一个空字符串而不是抛出异常(或其他东西)。

For example, if you only want objects that have a Name property, you could do something like: 例如,如果只需要具有Name属性的对象,则可以执行以下操作:

private static string GetName<T>(T input)
{
    var nameProperty =
        typeof (T)
            .GetProperties()
            .FirstOrDefault(propInfo =>
                propInfo.Name.Equals("Name", StringComparison.OrdinalIgnoreCase));

    if (nameProperty == null)
    {
        throw new InvalidOperationException(
            "The input type does not have a name property");
    }

    return (string) nameProperty.GetValue(input);
}

You can't. 你不能 As mentioned in comments, List<> is a class. 如评论中所述, List<> 一个类。 Restricting it to classes will include it. 将其限制为类将包括它。

This is an unfortunate case where you'll probably have to simply rely on the contract being used by calling code, and throw an exception for invalid arguments. 这是一种不幸的情况,您可能必须仅依靠调用代码所使用的协定,并为无效参数抛出异常。

public static string GetName<T>(T Object)
{
    if(Object is IEnumerable) throw new ArgumentException();
    xxxxxxx
}

Another option might be to add an overload that takes an IEnumerable . 另一个选择可能是添加一个采用IEnumerable的重载。 It's not super pretty, and you might not need it, but at least then the compiler will choose that and return something appropriate. 它不是很漂亮,您可能不需要它,但是至少编译器会选择它并返回合适的东西。

public static IEnumerable<string> GetName<T>(IEnumerable<T> Objects)
{
    return Objects.Select(GetName);
}

Be careful with this, though, because it can sometimes be difficult to predict (or rather, to remember to predict) which one will be called. 但是,请谨慎操作,因为有时可能很难预测(或更确切地说,要记住预测)将调用哪一个。

List<int> ints = new List<int>();

GetName(ints); // calls the IEnumerable version

object intsObj = (object)ints;
GetName(intsObj); // calls the non-IEnumerable version.

More generally speaking, though, it sounds like you might be setting up a less-than-ideal contract here. 但是,从更一般的意义上讲,听起来您可能在这里建立了一个不理想的合同。 If you're doing something like this with unfiltered generics, you'll probably want to be able to handle collections in it as well, and indeed I'm not sure why you wouldn't be able to. 如果您正在使用未经过滤的泛型执行此类操作,那么您可能还希望能够处理其中的集合,而实际上我不确定为什么无法这样做。 They're objects just like anything else. 它们是对象,就像其他任何对象一样。

If you are trying to restrict it, you'll probably want an interface or base class from which all objects passed to this method must be inherited. 如果想限制它,你可能会想从中传递给这个方法,所有对象必须继承的接口或基类。 That will significantly cut down your options for passing .NET classes in, but I can't imagine what use those would have anyway, if you need to get a "name" from something. 这将大大减少传递.NET类的选项,但是如果您需要从某些东西中获取“名称”,我将无法想象它们的用途。

If you go that route, you have two options: 如果您走那条路线,则有两种选择:

  • Restrict the parameter itself 限制参数本身
  • Restrict the generic argument 限制通用参数

The choice there depends on the contents and return type of the method, but I'd probably go with the former. 那里的选择取决于方法的内容和返回类型,但我可能会选择前者。

public static string GetName<T>(IObjectWithName Object)
{
    return Object.Name;
}

That's not particularly interesting as an example, though, so here's how you would restrict the generics. 作为示例,这并不是特别有趣,因此这是您将如何限制泛型的方法。

public static string GetName<T>(T Object)
    where T : IObjectWithName
{
    return Object.Name;
}

Just remember that your object needs to implement that interface--you can't pass a DateTime , for instance, to this method and expect it to work. 只要记住您的对象需要实现该接口即可,例如,您不能将DateTime传递给此方法,并且期望它可以工作。 If you expect "random" input like that, you'll probably need to set yourself up to receive collection types as well. 如果您希望这样的“随机”输入,则可能还需要设置自己以接收集合类型。


I should mention, just for good practice, that naming your parameters Object is not a good habit. 我应该提一下,只是为了好的实践,给参数Object命名不是一个好习惯。 That's a keyword (or rather, a System-level type) in C#. 那是C#中的关键字(或更确切地说,是系统级别的类型)。 So you could wind up with conflicts. 这样您就可以解决冲突了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM