带有对象初始化器和 LINQ 的 Ninject

发布于 2024-10-20 08:14:51 字数 1452 浏览 1 评论 0原文

我是 Ninject 的新手,所以我正在尝试的可能根本不可能,但我想问一下。以下是我随意写的,所以可能有错别字。假设我有一个接口:

public interface IPerson
{
    string FirstName { get; set; }
    string LastName { get; set;}

    string GetFullName();
}

和一个具体的:

public class Person : IPerson
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string GetFullName()
    {
        return String.Concat(FirstName, " ", LastName);
    }
}

当我从数组或 xml 检索数据时,我习惯做这样的事情:

public IEnumerable<IPerson> GetPeople(string xml)
{
    XElement persons = XElement.Parse(xml);

    IEnumerable<IPerson> people = (
        from person in persons.Descendants("person")
        select new Person
        {
            FirstName = person.Attribute("FName").Value,
            LastName = person.Attribute("LName").Value
        }).ToList();

    return people;
}

我不想以这种方式将具体与接口紧密耦合。我无法找到有关将 Ninject 与 LINQ to Objects 或对象初始值设定项一起使用的任何信息。我可能找错了地方,但我已经找了一天了,但一点运气都没有。

我正在考虑将内核放入单例实例中,看看这是否可行,但我不确定是否可行,而且我听说传递内核是一件坏事。我目前正在尝试在类库中实现这一点。如果这是不可能的,是否有人有任何关于这种情况下最佳实践的示例或建议?预先感谢您的帮助。

编辑: 根据一些答案,我觉得我应该澄清一下。是的,上面的例子看起来很短暂,但这只是我试图做的一个例子。让我们看一下更大的图景。假设我通过第 3 方 Web 服务收集所有数据,并为其创建一个接口,而不是 XML,该数据可以是 wsdl 中定义的对象,有时也可以是 xml 字符串。 IPerson 可用于 Person 对象和 User 对象。我将在一个单独的类库中执行此操作,因为它需要可移植并且将在其他项目中使用,并将其交给 MVC3 Web 应用程序,并且对象也将在 javascript 中使用。我感谢迄今为止所有的意见。

I'm new to Ninject so what I'm trying may not even be possible but I wanted to ask. I free-handed the below so there may be typos. Let's say I have an interface:

public interface IPerson
{
    string FirstName { get; set; }
    string LastName { get; set;}

    string GetFullName();
}

And a concrete:

public class Person : IPerson
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string GetFullName()
    {
        return String.Concat(FirstName, " ", LastName);
    }
}

What I'm used to doing is something like this when I'm retrieving data from arrays or xml:

public IEnumerable<IPerson> GetPeople(string xml)
{
    XElement persons = XElement.Parse(xml);

    IEnumerable<IPerson> people = (
        from person in persons.Descendants("person")
        select new Person
        {
            FirstName = person.Attribute("FName").Value,
            LastName = person.Attribute("LName").Value
        }).ToList();

    return people;
}

I don't want to tightly couple the concrete to the interface in this manner. I haven't been able to find any information in regards to using Ninject with LINQ to Objects or with object initializers. I may be looking in the wrong places, but I've been searching for a day now with no luck at all.

I was contemplating putting the kernel into an singleton instance and seeing if that would work, but I'm not sure that it will plus I've heard that passing your kernel around is a bad thing. I'm trying to implement this in a class library currently. If this is not possible, does anyone have any examples or suggestions as to what the best practice is in this case? Thanks in advance for the help.

EDIT:
Based on some of the answers I feel I should clarify. Yes, the example above appears short lived but it was simply an example of one piece that I was trying to do. Let's give a bigger picture. Say instead of XML I am gathering all my data through a 3rd party web service and I'm creating an interface for it, the data could be a defined object in the wsdl or it could sometimes be an xml string. IPerson could be used for both the Person object and a User object. I will be doing this inside of a separate class library, because it needs to be portable and will be used in other projects, and handing it to an MVC3 Web Application and the objects will be used in javascript as well. I appreciate all the input so far.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

‘画卷フ 2024-10-27 08:14:51

您的 Person 类是一个短暂的对象,它不适合用于依赖项注入。除此之外,它不包含任何行为,只是一个 POCO(普通旧 CLR 对象)。因为 POCO 不依赖于任何值得抽象的东西,所以通常没有理由抽象它们。换句话说:用给定的例子。您不需要 IPerson 界面。您可以在整个应用程序中直接使用 Person 类。

不过,GetPeople 方法通常可以是您使用 DI 配置抽象出来的服务的一部分。然而,包含 GetPeople(string xml) 方法的服务接口可能是一个错误的抽象,因为这意味着您将始终提供 xml 字符串。当您拥有此 XML 字符串时,是否有任何理由以任何其他方式解析该 XML 字符串?如果有一个带有 GetAllPeople() 方法的 IPersonRepository 接口会更方便。给定的实现可以是使用 XML 数据源(从磁盘、数据库或谁知道什么)获取人员的 XmlPersonRepository

Your Person class is a short lived object and it doesn't lend itself well to be used for dependency injection. Besides this, it doesn't contain any behavior and is simply a POCO (plain old CLR object). Because POCOs don't depend on anything worth abstracting, there is usually no reason to abstract them. In other words: With the given example. you don't need an IPerson interface. You can work directly with the Person class throughout your application.

The GetPeople method though, could typically be part of a service that you would abstract away using your DI configuration. A service interface that contains the GetPeople(string xml) method however, would probably be a wrong abstraction, because this means you would always supply an xml string. When you have this XML string, would there be any reason to ever parse that XML string in any other way? It would be more convenient to have an IPersonRepository interface with a GetAllPeople() method. A given implementation could be the XmlPersonRepository that uses an XML data source to fetch the people (from disk, database or who knows what).

沦落红尘 2024-10-27 08:14:51

您的 IPerson 接口是否有多个实现? (我对此表示怀疑,因为 Person 似乎只是一个被传递的数据对象。)也许我没有抓住你的问题的要点,但 DI 是为了分离关注点并从接口设计中抽象实现。

我不明白 DI 如何帮助您从定义的 XML 模式中提取 Person 对象。您正在解析数据,而不是动态注入实现。也许如果您想以不同的方式解析 XML 来比较性能,您可以创建包含 GetPeople 的类的替代实现,但我不认为这是您的问题的重点。

Do you have more than one implementation of your IPerson interface? (I doubt it since it seems that Person is simply a data object that gets passed around.) Perhaps I'm missing the point of your question but DI is for separation of concerns and abstracting implementation from interface design.

I don't see how DI can help you extract a Person object from a defined XML schema. You're parsing data, not injecting an implementation dynamically. Perhaps if you wanted to parse the XML a different way to compare performance you would create alternative implementations of the class containing GetPeople, but I don't see that as the point of your question.

如果没结果 2024-10-27 08:14:51

Ninject 能为您做的就是为您提供 IPerson 的实现。它不会解析您的 XML 或其他结构。事实上,您很可能会丢失对象初始化语法,因为您必须通过 ninject 内核或服务定位器。

我建议您使用一个序列化库来完成您想做的事情。我推荐 json.net 或 .NET 内置的 XML 序列化

All Ninject could do for you would be to get you an implementation of IPerson. It will not parse your XML or other structure. In fact you would most likely lose the object initialization syntax because you would have to go through the ninject kernel or a service locator.

I would suggest a serialization library for what you want to do. I would recommend json.net or .NET's built in XML serialization

烟织青萝梦 2024-10-27 08:14:51

通常情况下,我会简单地假设这里拥有 20k 以上代表的任何人可能比我更了解这些东西。然而,在我看来:

1)你的例子与 Ninject 网站上使用的例子相差不远
2)即使“这个”特定示例不是一个好示例,当前的问题是使用对象初始值设定项,并且这可以适用于任何其他数量的更合法的场景。

不幸的是,我没有关于如何使用 Ninject 进行对象初始化的答案,但我确实有一个关于“在哪里”使用 Ninject 的建议,这可能会有所帮助(我意识到这篇文章已经有一年了,但也许这会对某人有所帮助) 。

我同意您很可能应该在 GetPeople() 方法中使用具体类,因为该方法可能是特定于 Person 的实现的一部分(并且可能位于同一程序集和/或命名空间中)。但是,当您有类似表单之类的东西向用户呈现有关 Person 的信息时,我应该认为它应该与 IPerson 一起使用,而不是与具体实现一起使用。

您主要需要使用对象初始值设定项以便利用 linq 的地方是在像 GetPeople 这样的方法中,您应该在其中使用具体的类,所以我相信您应该能够两全其美。不,在使用 IPerson 时,您将无法在表单中使用对象初始值设定项,但我认为如果您想在GetPeople 方法。

编辑:实际上,您不需要“需要”对象初始值设定项来使用 linq 。

如果您放弃一些语法糖,您可以重写

IEnumerable<IPerson> people = ( 
    from person in persons.Descendants("person") 
    select new Person 
    { 
        FirstName = person.Attribute("FName").Value, 
        LastName = person.Attribute("LName").Value 
    }).ToList(); 

As

IEnumerable<IPerson> people = 
    (persons.Descendants("person")
           .Select(o => 
           { 
               var p = new Person();
               p.FirstName = person.Attribute("FName").Value;
               p.LastName = person.Attribute("LName").Value;
               return p;
           }).ToList();

并且您可以看到如何修改它以轻松地使用注入。

Normally, I would simply assume anyone with 20k+ rep here probably knows more than I do about this stuff. However, it also seems to me that:

1) Your example is not too far removed from the examples used on the Ninject website
2) Even if 'this' particular example isn't a good one the issue at hand is using object initializers and that could apply to any other number of more legitimate scenarios.

Unfortunately I don't have an answer on how to do object initialization with Ninject, but I do have a suggestion on 'where' to use Ninject that might help (and I realize this post is a year old but maybe this will help someone).

I agree that you should most likely be using the concrete classes in the GetPeople() method because that method is probably part of an implementation that is specific to Person (and is likely in the same assembly and/or namespace). However, when you have something like a form that is presenting information to a user about a Person then I should think it ought to work with IPerson rather than the concrete implementation.

The place you mainly need to use the object initializers in order to take advantage of linq though is in methods like GetPeople where you ought to work with the concrete classes though so I believe you should be able to have the best of both worlds. No, you wouldn't be able to use an object initializer in the form when working with an IPerson, but I don't think that you would ever 'need' to in that way you need to if you want to use linq in the GetPeople method.

Edit: Actually you don't 'need' object initializers to use linq here

If you forgo some syntactic sugar you can rewrite

IEnumerable<IPerson> people = ( 
    from person in persons.Descendants("person") 
    select new Person 
    { 
        FirstName = person.Attribute("FName").Value, 
        LastName = person.Attribute("LName").Value 
    }).ToList(); 

As

IEnumerable<IPerson> people = 
    (persons.Descendants("person")
           .Select(o => 
           { 
               var p = new Person();
               p.FirstName = person.Attribute("FName").Value;
               p.LastName = person.Attribute("LName").Value;
               return p;
           }).ToList();

And you can see how that could be modified to work with injection quite easily.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文