Ninject with Object Initializers和LINQ

时间:2011-03-05 16:58:32

标签: c# linq dependency-injection ninject object-initializers

我是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或对象初始化器一起使用的信息。我可能正在寻找错误的地方,但我一直在寻找一天没有运气。

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

修改 基于一些答案,我觉得我应该澄清一下。是的,上面的例子似乎很短暂,但它只是我试图做的一件事的一个例子。让我们来看一个更大的图景。说而不是XML我通过第三方Web服务收集我的所有数据,并且我正在为它创建一个接口,数据可以是wsdl中的已定义对象,或者有时可能是xml字符串。 IPerson可以用于Person对象和User对象。我将在一个单独的类库中执行此操作,因为它需要是可移植的,并将在其他项目中使用,并将其交给MVC3 Web应用程序,并且这些对象也将在javascript中使用。到目前为止,我很欣赏所有的意见。

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

您的IPerson界面是否有多个实现? (我怀疑它,因为Person似乎只是一个传递的数据对象。)也许我错过了你的问题的重点,但DI是用于分离关注点和从接口设计中抽象实现。

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

答案 2 :(得分:1)

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

我建议你做一个序列化库来做你想做的事情。我会推荐json.net或.NET's built in XML serialization

答案 3 :(得分:0)

通常,我只是假设任何拥有20k + rep的人可能比我对这些东西的了解更多。但是,在我看来:

1)您的示例与Ninject网站上使用的示例相差不多 2)即使'这个'特定的例子不是一个好的例子,手头的问题是使用对象初始化器,并且可以适用于任何其他数量的更合理的场景。

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

我同意您最有可能在GetPeople()方法中使用具体类,因为该方法可能是特定于Person的实现的一部分(并且可能在同一个程序集和/或命名空间中)。但是,当你有一个类似于向用户提供关于某个人的信息的表格时,我应该认为它应该与IPerson合作而不是具体的实现。

你主要需要使用对象初始化器才能利用linq的地方虽然是像GetPeople这样的方法,你应该使用具体的类,但我相信你应该能够兼顾两个世界的优点。不,你在使用IPerson时无法在表单中使用对象初始化程序,但我不认为你需要以这种方式需要,如果你想使用linq 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(); 

作为

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();

你可以很容易地看到如何修改它以便与注射配合使用。