2009-08-07 68 views
1

我有一个简单的问题。这段代码看起来真的不对。如果适用,我想利用泛型和代表以及很可能的泛型代表。我正在使用一些代码生成API,生成的对象非常相似。我看到他们都实现了一个接口,所以我试图用一些方法来创建一个类来处理不同的场景。这里是一些示例代码。它在这么多层面上感觉不对。请告诉我如何让这段代码更好。如果你愿意,可以提供一些重构建议。并通过一切手段将其撕成碎片。我想更好地编写代码并学会正确地做事。根据类型分配一个委托?

private delegate IsomeEntity DisplayDelegate(IsomeEntity display); 

public IsomeEntity Display<T>() 
{ 
    DisplayDelegate _del = null; 
    IsomeEntity display = factory.CreateObject(typeof(T).Name); 

    if (display.GetType() == typeof(ADisplayEntity)) 
     _del = ADisplayEntity; 

    if (display.GetType() == typeof(BDisplayEntity)) 
     _del = BDisplayEntity; 

    if (display.GetType() == typeof(CDisplayEntity)) 
     _del = CDisplayEntity; 


    return _del(display); 
} 

public ADisplayEntity ADisplayEntity(IsomeEntity display) 
{ 
    ADisplayEntity ade = display as ADisplayEntity; 

    try 
    { 
     ADisplay o = new ADisplay(); 
     ADisplayEntity response = o.ADisplay(ade); 
     return response; 
    } 
    catch (Exception ex) 
    { 
     Exception newEx; 
     if (someExceptionHandler.HandleException(ex, this, out newEx)) 
      throw newEx; 
    } 

    return null; 
} 

public BDisplayEntity BDisplayEntity(IsomeEntity display) 
{ 
    BDisplayEntity dde = display as BDisplayEntity; 

    try 
    { 
     BDisplay o = new BDisplay(); 
     BDisplayEntity response = o.BDisplay(bde); 
     return response; 
    } 
    catch (Exception ex) 
    { 
     Exception newEx; 
     if (someExceptionHandler.HandleException(ex, this, out newEx)) 
      throw newEx; 
    } 

    return null; 
} 

回答

0

您可以通过委托和lambda函数作为通用值,所以是这样的:那么

public ISomeEntity Display<T>(Func<T, ISomeEntity> conversion) 
{ 
    IsomeEntity display = factory.CreateObject(typeof(T).Name); 
    return conversion(display); 
} 

调用,这将是:

var myNewEntity = Display( 
    x => ADisplay.GetADisplay(x as ADisplayEntity)); 

等。

我不完全确定你要做什么 - 所以我的代码可能不太对,但它应该给你和想法,你怎么可以传递lambdas左右。

你甚至可以将它们存储在字典中并查找它们。

+0

我认为他想的显示方法的代码,使他不必指定它的每一个他想要的ISomeEntity – Randolpho 2009-08-07 15:42:45

0

好的,如果我正确地跟着你,ADisplayEntityBDisplayEntity都是生成类看起来几乎相同,对吧?并且您正在尝试创建某种通用委托工厂方法(您称为Display<T>),该方法允许调用方指定他们需要的显示实体的类型,将其作为您创建实体实现的单个接口进行投射,是?我认为ADisplayBDisplay类没有实现通用的Display()方法,这就是为什么你要拨打ADisplayBDisplay。嗯...那些和班上的名字一样。错字?你列出的内容甚至不会编译。

我认为需要一个更好的例子。我意识到你正试图清理你的代码,但也许一些真正的名称改变的代码可能会更好。我想看看ADisplayBDisplayADisplayEntityBDisplayEntity真的是。也就是说,如果各种类型的真的如此不同以至于你不能将这些委托方法合并成一个方法,那么你几乎可以做唯一的事情来实现你的原始目标。

也许随着更多的信息我可以提供更好的答案,但我没有看到太多的重构在这里。除了方法的名称与它们实例化的类相同的名称,以及对与该类名称相同的方法的调用之外。

0

为什么不像简单的东西?为什么你需要delegates..etc

public static ISomeEntity DisplayEntity(ISomeEntity display) 
{ 

     ISomeEntity result; 
      if (entity is ADisplayEntity) 
      { 
       ADisplay disp = new ADisplay(); 
       result = disp.ADisplayFunc(); 
      } 
      if(entity is BDisplayEntity) 
      { 
       BDisplay disp = new BDisplay(); 
       result = disp.BDisplayFunc(); 
      } 

    return result; 
} 

当然会更有意义,如果你可以有你的A显示BDisplay也跟着接口,像IDisplay,那么你只需要返回中IDisplay。显示(ISomeEntity)

要遵循,你可以换你的显示器这样的..

public interface IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity); 
} 

public class AWrappedDisplay: IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     ADisplay disp = new ADisplay(); 
     return disp.ADisplayFunc(entity); 
    } 

} 

public class BWrappedDisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     BDisplay disp = new BDisplay(); 
     return disp.BDisplayFunc(entity); 
    } 

} 

public static IDisplay Factory(Type t) 
     { 
      IDisplay disp = null; 
      if (t == typeof(ADisplayEntity)) 
       disp = new AWrappedDisplay(); 

      if (t == typeof(BDisplayEntity)) 
       disp = new BWrappedDisplay(); 

      return disp; 
     } 

,然后你可以叫你DisplayEntity这样

public static ISomeEntity DisplayEntity(ISomeEntity display) 
    { 
     IDisplay disp = Factory(display.GetType()); 
     ISomeEntity newDisplayEntity = disp.Display(display); 

     return newDisplayEntity; 
    } 
0

如果你想概括那些方法你可以这样做:

private delegate IsomeEntity DisplayDelegate<T>(IsomeEntity display); 

    public IsomeEntity DisplayMethod<T>() where T : IsomeEntity 
    { 
     DisplayDelegate<T> _del = new DisplayDelegate<T>(DoDisplay<T>); 
     IsomeEntity entity = factory.CreateObject(typeof(T).Name); 

     return _del(entity); 
    } 

    public IsomeEntity DoDisplay<T>(IsomeEntity entity) 
    { 
     try 
     { 
      Display<T> o = new Display<T>(); 
      Entity<T> response = o.Display(entity); 
      return response; 
     } 
     catch (Exception ex) 
     { 
      if (someExceptionHandler.HandleException(ex, this, out newEx)) 
       throw newEx; 
     } 
    } 

在这种情况下,代理真的没有必要,您可以直接调用DoDisplay。

public IsomeEntity DisplayMethod<T>() where T : IsomeEntity 
    {    
     IsomeEntity entity = factory.CreateObject(typeof(T).Name); 

     return DoDisplay<T>(entity); 
    } 

    public IsomeEntity DoDisplay<T>(IsomeEntity entity) 
    { 
     try 
     { 
      Display<T> o = new Display<T>(); 
      Entity<T> response = o.Display(entity); 
      return response; 
     } 
     catch (Exception ex) 
     { 
      if (someExceptionHandler.HandleException(ex, this, out newEx)) 
       throw newEx; 
     } 
    } 
+1

当我看到你在做什么,在这里,但你的例子难道不编译,什么类型究竟是* o *,* o *如何具有* o.Display(实体)* – 2009-08-07 16:07:43

+0

我基于OP上的示例,OP具有“ADisplay”和“BDisplay”。因为它是通用的,我只是将它重命名为“Display”。 这个例子是针对语法和设计的,它没有包含实际编译,构建和运行所需的所有东西。实施细节留给用户。 – 2009-08-07 17:17:33

0

我会因为你提到的东西是自动生成,修改ISomeEntity是窗外的假设(否则我建议增加一个显示()方法来ISomeEntity,然后就调用它直接作用于实体通过接口,每个实体将实现他们自己的Display()版本)。所以,如果我理解你的代码试图做的是正确的(这不是很清楚),我建议创建一个IDisplay接口,让ADisplay和BDisplay从它继承。这个接口将有一个方法Display(),它采用ISomeEntity并返回ISomeEntity。但是,如果ADisplay.Display(ISomeEntity)收到BDisplayEntity,则会引发异常。

然后,我会创建一个IDictionary,它将存储为具有该主Display方法(我将称之为Displayer)的类中的字段。该字典将存储每种类型使用的IDisplay(即typeof(ADisplayEntity) - > new ADisplay())。

然后,您可以将您的主要Display方法添加到Displayer中,但现在使其返回一个泛型T,因为T是您正在创建和返回的类型。此方法查找它需要的IDisplay,并在工厂创建的ISomeEntity上使用它,并返回结果。

该词典的使用意味着您不会收到糟糕的一批if语句,并且只需添加到字典中即可轻松添加更多IDisplays。

这是我的代码,它在VS2008中编译。

public interface ISomeEntity 
{ 

} 

public class EntityFactory 
{ 
    public ISomeEntity CreateObject(string name) 
    { 
     //Do factory stuff here 
     return null; 
    } 
} 

public class ADisplayEntity : ISomeEntity 
{ 
} 



public class BDisplayEntity : ISomeEntity 
{ 
} 

public interface IDisplay 
{ 
    ISomeEntity Display(ISomeEntity entity); 
} 

public class ADisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     ADisplayEntity aEntity = entity as ADisplayEntity; 
     if (aEntity == null) 
      throw new ArgumentException("Wrong type"); 

     //Do whatever happens when you convert parameter entity into a 
     //"response" ADisplayEntity. I'm just returning a new 
     //ADisplayEntity to make it compile for me 
     return new ADisplayEntity(); 
    } 
} 

public class BDisplay : IDisplay 
{ 
    public ISomeEntity Display(ISomeEntity entity) 
    { 
     BDisplayEntity bEntity = entity as BDisplayEntity; 
     if (bEntity == null) 
      throw new ArgumentException("Wrong type"); 

     //Do whatever happens when you convert parameter entity into a 
     //"response" BDisplayEntity. I'm just returning a new 
     //BDisplayEntity to make it compile for me 
     return new BDisplayEntity(); 
    } 
} 



public class Displayer 
{ 
    private IDictionary<Type, IDisplay> displayers; 
    private EntityFactory factory; 


    public Displayer() 
    { 
     factory = new EntityFactory(); 
     displayers = new Dictionary<Type, IDisplay> 
         { 
          { typeof(ADisplayEntity), new ADisplay() }, 
          { typeof(BDisplayEntity), new BDisplay() } 
         }; 
    } 


    public T Display<T>() where T : class, ISomeEntity 
    { 
     T entity = factory.CreateObject((typeof(T).Name)) as T; //Type-safe because of the factory 
     IDisplay displayer = displayers[typeof(T)]; 
     return displayer.Display(entity) as T; //Typesafe thanks to each IDisplay returning the correct type 
    } 
}