C # метод, который принимает несколько объектов, которые имеют общие свойства? - PullRequest
3 голосов
/ 14 декабря 2011

У меня есть несколько объектов с несколькими свойствами, которые являются общими для всех них. Например:

Объект A относится к типу X и имеет 10 свойств

Объект B имеет тип Y и обладает 15 свойствами

Объект C имеет тип Z и имеет 7 свойств

Все эти объекты имеют общие свойства "имя", "подпись" и "контрольная сумма". Я пытаюсь создать статический вспомогательный метод, который может принимать объект любого типа, который содержит свойства «имя», «подпись» и «контрольная сумма». Это возможно, или мне действительно нужно три разных метода (один для принятия объекта каждого типа)?

РЕДАКТИРОВАТЬ - Я не упомянул, что эти объекты открыты для меня через веб-сервис.

Ответы [ 8 ]

8 голосов
/ 14 декабря 2011

Вы должны переместить эти свойства в общий базовый класс или интерфейс и использовать их.

4 голосов
/ 14 декабря 2011

У вас есть два хороших варианта. Первое наследство:

public class CommonObject
{
    public string Name;
    public string Signature;
    public string Checksum;
}

public class X : CommonObject
{
    // other properties
}

public class Y : CommonObject
{
    // other properties
}

public class Z : CommonObject
{
    // other properties
}

public static void DoSomething(CommonObject o)
{
    // You can access these values
    if (o.Name == "" || o.Signature == "")
        o.Checksum = 0;
}

Это может быть очень полезно, поскольку вы можете сделать эти свойства виртуальными, и каждый класс может переопределять их по-разному.

Второй вариант использует интерфейс:

public class OtherClass
{
    public static void DoSomething(CommonObject o)
    {
        // code here
    }
}

public interface CommonObject
{
    string Name { get; }
    string Signature { get; }
    string Checksum { get; }
}

public class X : CommonObject
{
    private string _name = "";
    private string _signature = "";
    private string _checksum = "";

    string CommonObject.Name { get { return _name; } }
    string CommonObject.Signature { get { return _signature; } }
    string CommonObject.Checksum { get { return _checksum; } }
}
2 голосов
/ 15 декабря 2011

Я собираюсь предположить, что, поскольку эти объекты открываются через веб-сервис, вы не можете контролировать определение объекта.Они такие, какие есть, и их нельзя наследовать от общего базового класса или интерфейса.С этим ограничением проблемы у вас действительно есть только две опции.

Если вы используете C # 4.0 или новее, вы можете использовать новый тип dynamic .По сути, это ссылка на объект, которая не выполняет никакой оценки типа до времени выполнения.Поэтому, если свойство или метод, который вы используете для динамического типа, не существует, вы получите ошибку времени выполнения, а не ошибку во время компиляции.

Другой опион собирается просто взять ссылку на тип Object и использовать отражение для управления свойствами и методами.Там много уродливого потенциала.

Если вы не используете C # 4+, тогда я думаю, что я бы выбрал три отдельных метода.Хотя вы могли бы дублировать некоторый код, я бы предпочел иметь его, а не набор сложных сложных для отслеживания вызовов рефлексии, которые вам придется использовать в c # 3.5-

2 голосов
/ 14 декабря 2011

Для другого варианта есть также динамическая печать . Хотя эта опция должна работать для вас, я определенно попытался бы использовать интерфейс или базовый класс, как уже упоминали другие.

2 голосов
/ 14 декабря 2011

интерфейс - ваш лучший вариант, я полагаю,

public interface ISomeGoodNameForCommonProperies 
{
  string Name {get;set;}
  string Signature {get;set;}
  string Checksum {get;set;}
}

public class X : ISomeGoodNameForCommonProperies 
{
  string Name {get;set;}
  string Signature {get;set;}
  string Checksum {get;set;}
  ...
}

public class Y : ISomeGoodNameForCommonProperies 
{
  string Name {get;set;}
  string Signature {get;set;}
  string Checksum {get;set;}
  ...
}

public class Z : ISomeGoodNameForCommonProperies 
{
  string Name {get;set;}
  string Signature {get;set;}
  string Checksum {get;set;}
  ...
}

ваш вспомогательный метод, тогда ISomeGoodNameForCommonProperies

public object MyHelperMethod(ISomeGoodNameForCommonProperies myObject)
{
  ...
}

наследование будет работать, конечно, однако я бы избегал базовых классовесли это не имеет смысла для объектов, которые вы пытаетесь создать.вопрос, который вы должны задать себе, можно ли определить X, Y и Z как некоторый тип другого объекта O?если это так, продолжайте и создайте O и присуще ему.Если этих трех общих свойств недостаточно для определения логической сущности, но их необходимо сгруппировать по практическим соображениям, интерфейс является вашим лучшим вариантом.

2 голосов
/ 14 декабря 2011

Это возможно возможно ... если вы определяете общий базовый класс, содержащий общие методы, и делаете подклассы объектов A, B и C базового. Ваш статический вспомогательный метод может затем использовать базовый класс в качестве своего типа параметра, и в него может быть передан любой из подтипов.

1 голос
/ 14 декабря 2011

Существует два подхода к этой проблеме:

Создайте базовый класс, который имеет все эти общие свойства, и извлеките из него другие.

public abstract class MyBaseClass
{
    public string Name { get; set; }
    public string Signature { get; set; }
    public int Checksum { get; set; }
}

public class ClassX : MyBaseClass
{
    // Add the other properties here
}

public class ClassY : MyBaseClass
{
    // Add the other properties here
}

public class ClassZ : MyBaseClass
{
    // Add the other properties here
}

Ваш вспомогательный метод будет иметь параметр типа MyBaseClass:

public void MyHelperMethod(MyBaseClass obj)
{
    // Do something with obj.Name, obj.Siganture and obj.Checksum
}

Также было бы неплохо поместить вспомогательный метод в MyBaseClass, но без параметров, поскольку теперь он может обращаться к свойствам напрямую:

public abstract class MyBaseClass
{
    public string Name { get; set; }
    public string Signature { get; set; }
    public int Checksum { get; set; }

    public void CreateChecksum() // Your helper method
    {
        Checksum = Name.GetHashCode() ^ Signature.GetHashCode();
    }
}

Тогда вы можете позвонить прямо из ваших объектов:

objA.CreateChecksum();
objB.CreateChecksum();
objB.CreateChecksum();

Или определите интерфейс, который реализуют ваши три класса:

public interface IMyInterface
{
    string Name { get; set; }
    string Signature { get; set; }
    int Checksum { get; set; }
}

public class ClassX : IMyInterface
{
        public string Name { get; set; }
        public string Signature { get; set; }
        public int Checksum { get; set; }
    // Add the other properties here
}

public class ClassY : IMyInterface
{
        public string Name { get; set; }
        public string Signature { get; set; }
        public int Checksum { get; set; }
    // Add the other properties here
}

public class ClassZ : IMyInterface
{
        public string Name { get; set; }
        public string Signature { get; set; }
        public int Checksum { get; set; }
    // Add the other properties here
}

Ваш вспомогательный метод будет иметь параметр типа IMyInterface:

public void MyHelperMethod(IMyInterface obj)
{
    // Do something with obj.Name, obj.Siganture and obj.Checksum
}

Вы можете вызвать MyHelperMethod следующим образом

MyHelperMethod(objA);
MyHelperMethod(objB);
MyHelperMethod(objC);
1 голос
/ 14 декабря 2011

Вы можете использовать наследование .

...