如何在C#.NET中将对象修剪为其基础对象?

时间:2012-05-09 10:16:23

标签: c# .net security inheritance polymorphism

考虑以下方法:

public PrintObjectHierarchy(object o)
{
   Console.WriteLine(o.GetType.FullName);

   object baseObject = PruneObjectToItsBaseObject(o);
   if(!baseObject.GetType().Equals(typeof(object)))
       PrintObjectHierarchy(baseObject);
   else Console.WriteLine("System.Object");
}

例如,如果我写道:

class Form1 : Form
{
  static void Main()
  {
    Form1 f1 = new Form1();
    PrintObjectHierarchy(f1);
  }
}

然后它应该打印给我:

MyNamespace.Form1
System.Windows.Form
System.Windows.Forms.ContainerControl
/*and so so till...*/
System.Object

但不幸的是,即使我将CAST对象转换为其BaseType,“C#Polymorphism”也会将其 VIEW 限制为基本类型,并且不会返回 REAL 引用一个 REAL 基础对象给我!让我们通过一个例子来描述它;如果我有

class Person {
public string Name;
public string LastName;
}
class President : Person {
public string password;
}

main(){
President pr = new President() {Name="John"; LastName="Smith"; password="js123" };
Person p = (Person)pr;
SendToAirportSystemAcrossInternet(p);
}

虽然我们认为 p ,但事实并非如此!它是总统 p 只是一个视图,因此总统的密码将通过互联网传播!

关于如何修剪或切片对象的任何想法是创建真实基础对象的基础吗?

提前致谢!

4 个答案:

答案 0 :(得分:2)

丹尼尔的解决方案有效;另一种类似的方法是编写一个“复制构造函数”并以这种方式创建一个新人。

所以,你的班级成为:

public class Person
{
    public Person()
    {
    }

    public Person(Person p)
    {
        this.name = p.name;
        this.lastName = p.lastName
    }

    public string name;
    public string lastName;
}

你可以从像这样的总统创建一个人:

President pres = new President() { name = "abc", lastName = "def", password = "kittens" };
Person p = new Person(pres);

这会从总统那里创造一个人,但是没有办法回到总统那里,也无法获得密码。如果你创建了一个这样的人并投给了一位总统,你将获得一个InvalidCastException,我认为这就是你想要的。

答案 1 :(得分:2)

你想要实现的目标并不是很明显,但是当你对对象的继承层次结构感兴趣时,你很可能想要处理System.Type的实例。这是您发布的第一个方法的工作版本,可能会提示您如何从那里继续:

static void PrintObjectHierarchy(object o)
{
    Type t = o.GetType();
    while (t != null)
    {
        Console.WriteLine(t.FullName);
        t = t.BaseType;
    }
}

答案 2 :(得分:1)

基本上,你不能做你想做的事。你应该重新设计,以便你没有这个要求。

正如我在评论中所指出的,当执行时类型是派生类时,基类中的一组字段可能是有效的,但对于该类的实例是无效的。此外,当以这种方式查看对象时,可能存在各种其他保护措施,这些保护措施简单地变为无效。例如,基类可以保存对值集合的引用,派生类期望验证添加到该集合的值。当对象被“修剪”时,将删除该验证,但是引用与之前相同的集合:

// EvenNumbersOnlyCollection rejects odd numbers
EvenNumberCollection derived = new EvenNumbersOnlyCollection();
NumberCollection pruned = Prune<NumberCollection>(derived);
pruned.Add(5);

// This would return 5 - the invariant is broken!
int shouldBeEven = derived.First();

目前尚不清楚为什么你认为这种修剪是个好主意,但你应该尝试以其他方式实现更广泛的目标。

答案 3 :(得分:0)

在C#中创建对象时,始终将其转换为其原始类型。即使您将其用作基础对象或接口,调用p.GetType()也将始终返回原始类型。

如果需要创建新对象,然后需要修剪其基础对象,则需要创建一个新的对象类型。例如:

public class ParentClass
{
  public Parent(int feature1)
  {
    mFeature1 = feature1;
  }
}

public class ChildClass : ParentClass
{
  public ChildClass(int feature1, int feature2) : base(feature1)
  {
    mFeature2 = feature2;
  }
}

...
...
ChildClass cc = new ChildClass(10, 20);
ParentClass pc = (ParentClass)cc; // pc still is of type ChildClass
ParentClass ccAsParent = new ParentClass(cc.Feature1); //ccAsParent is of type ParentClass
...
...

请记住,如果父类不是抽象,则只能执行此操作。