简体   繁体   English

在C#中铸造对象(ASP.Net MVC)

[英]Casting objects in C# (ASP.Net MVC)

I'm coming from a background in ColdFusion, and finally moving onto something modern, so please bear with me. 我来自ColdFusion的背景,最后进入了现代的东西,所以请耐心等待。

I'm running into a problem casting objects. 我在投放对象时遇到问题。 I have two database tables that I'm using as Models - Residential and Commercial. 我有两个用作模型的数据库表-住宅和商业。 Both of them share the majority of their fields, though each has a few unique fields. 尽管它们每个都有一些唯一的字段,但它们都共享大部分字段。 I've created another class as a container that contains the sum of all property fields. 我创建了另一个类作为包含所有属性字段总和的容器。 Query the Residential and Commercial, stuff it into my container, cunningly called Property. 查询“住宅和商业”,将其填充到我的容器中,这个容器被巧妙地称为“属性”。 This works fine. 这很好。

However, I'm having problems aliasing the fields from Residential/Commercial onto Property. 但是,我在将“住宅/商业”字段别名为“属性”时遇到问题。 It's quite easy to create a method for each property: fillPropertyByResidential(Residential source) and fillPropertyByCommercial(Commercial source), and alias the variables. 为每个属性创建一个方法很容易:fillPropertyByResidential(Residential source)和fillPropertyByCommercial(Commercial source),并对变量进行别名。 That also works fine, but quite obviously will copy a bunch of code - all those fields that are shared between the two main Models. 这也可以正常工作,但是很显然,它将复制一堆代码-在两个主要模型之间共享的所有那些字段。

So, I'd like a generic fillPropertyBySource() that takes the object, and detects if it's Residential or Commercial, fills the particular fields of each respective type, then do all the fields in common. 因此,我想要一个通用的fillPropertyBySource()来获取对象,并检测它是Residential还是Commercial,填充每种类型的特定字段,然后共同处理所有字段。 Except, I gather in C# that variables created inside an If are only in the scope of the if, so I'm not sure how to do this. 除此以外,我在C#中收集了在If内部创建的变量仅在if的范围内,因此我不确定如何执行此操作。

    public property fillPropertyBySource(object source)
    {
        property prop = new property();
        if (source is Residential)
        {
            Residential o = (Residential)source;
            //Fill Residential only fields

        }
        else if (source is Commercial)
        {
            Commercial o = (Commercial)source;
            //Fill Commercial only fields
        }
        //Fill fields shared by both
        prop.price = (int)o.price;
        prop.bathrooms = (float)o.bathrooms;

        return prop;
    }

"o" being a Commercial or Residential only exists within the scope of the if. 作为商业或住宅的“ o”仅存在于if的范围内。 How do I detect the original type of the source object and take action? 如何检测源对象的原始类型并采取措施?

Bear with me - the shift from ColdFusion into a modern language is pretty..... difficult. 忍受我-从ColdFusion到现代语言的转换非常.....困难。 More so since I'm used to procedural code and MVC is a massive paradigm shift. 更重要的是,由于我习惯了过程代码,因此MVC发生了巨大的范式转变。

Edit: I should include the error: The name 'o' does not exist in the current context For the aliases of price and bathrooms in the shared area. 编辑:我应该包括以下错误:名称'o'在当前上下文中不存在对于共享区域中价格和浴室的别名。

This is best done with an interface like this: 最好使用以下接口完成此操作:

public interface IProperty 
{
   int price { get; set; }
   float bathrooms { get; set; }
}

public class Residential : IProperty
{
   public int price { get; set; }
   public float bathrooms { get; set; }
   //Other stuff...
}

public class Commercial : IProperty
{
   public int price { get; set; }
   public float bathrooms { get; set; }
   //Other stuff...
}

Then in your method, take the interface instead of object: 然后在您的方法中,采用接口代替对象:

public property fillPropertyBySource(IProperty source)
{
    property prop = new property();
    if (source is Residential)
    {
        Residential o = (Residential)source;
        //Fill Residential only fields

    }
    else if (source is Commercial)
    {
        Commercial o = (Commercial)source;
        //Fill Commercial only fields
    }
    //Fill fields shared by both
    prop.price = source.price;
    prop.bathrooms = source.bathrooms;

    return prop;
}

An interface is used when your classes have common properties that you want to access. 当类具有要访问的公共属性时,将使用接口。 You could also have a base class Property with price and bathrooms and inherit from that instead, whichever you prefer. 您还可以拥有一个带有pricebathrooms的基类Property ,并从中继承,而无论您喜欢哪个。

Because of the artificial constraints imposed on you by using database-generated object types instead of hierarchically defined ones, there's really no elegant solution to this at all. 由于使用数据库生成的对象类型而不是按层次结构定义的对象类型对您施加了人为的约束,因此,实际上根本没有解决方案。 The best solution I can offer is to use a partial class to attach a known interface and then use overloading to do the minimum amount of work required when copying the object: 我可以提供的最佳解决方案是使用部分类来附加已知接口,然后使用重载来执行复制对象时所需的最少工作量:

interface IPropertyBase
{
    decimal Price { get; set; }
    int Bathrooms { get; set; }
}

partial class Residential : IPropertyBase
{
}

partial class Commercial : IPropertyBase
{
}

class Property : IPropertyBase
{
 public decimal Price { get; set; }
 public int Bathrooms { get; set; }

    // Commercial
    public int Offices { get; set; }

    // Residential
    public int Bedrooms { get; set; }

    private void CopyFromBase(IPropertyBase o)
    {
        Price = o.Price;
        Bathrooms = o.Bathrooms;
    }

    public void CopyFrom(Commercial o)
    {
        CopyFromBase(o);

        Offices = o.Offices;
    }

    public void CopyFrom(Residential o)
    {
        CopyFromBase(o);

        Bedrooms = o.Bedrooms;
    }
}

As a general note, "union" objects of this type are often a bad idea. 通常要注意的是,这种“联合”对象通常是个坏主意。 You're better off defining the common properties in an IPropertyBase interface and leaving the Residential/Commercial objects in their "native" form as you work with them. 最好在IPropertyBase接口中定义公用属性,并在使用它们时将“住宅/商业”对象保留为“本机”形式。 If you need to create a combined collection of all properties in an area, for example, create a List<IPropertyBase> and work directly with that -- it will keep the objects in the list intact (allowing you to determine their original type later using the is/as operators if you need) and it won't have the overhead of lots of empty, meaningless fields on each object. 例如,如果您需要创建一个区域中所有属性的组合集合,则创建一个List<IPropertyBase>并直接使用它-它将使列表中的对象保持完整(允许您稍后使用以下方法确定其原始类型) (如果需要,则为is / as运算符),并且不会在每个对象上产生很多空的,无意义的字段。

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

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