2011-01-08 57 views
4

我的GUI正在调用一个执行一些linq工作的服务项目,并将数据返回到我的GUI。但是,我正在与该方法的返回类型作斗争。经过一些阅读后,我有这个作为我的方法:Linq和返回类型

public static IEnumerable GetDetailedAccounts() 
{ 
IEnumerable accounts =(from a in Db.accounts 
         join i in Db.financial_institution on 
          a.financial_institution.financial_institution_id 
           equals i.financial_institution_id 
         join acct in Db.z_account_type on a.z_account_type.account_type_id 
           equals acct.account_type_id 
         orderby i.name 
         select new 
          { 
           account_id = a.account_id, 
           name = i.name, 
           description = acct.description 
           }); 
      return accounts; 
} 

但是,我的来电者有点争斗。我认为我搞砸了返回类型,或者没有很好地处理调用者,但它并不像我希望的那样工作。

这就是我试图从我的GUI调用方法。

IEnumerable accounts = Data.AccountService.GetDetailedAccounts(); 

Console.ForegroundColor = ConsoleColor.Green; 
Console.WriteLine("Accounts:"); 
Console.ForegroundColor = ConsoleColor.White; 

foreach (var acc in accounts) 
    { 
    Console.WriteLine(string.Format("{0:00} {1}", acc.account_id, acc.name + " " + acc.description)); 
    } 

int accountid = WaitForKey(); 

但是,我的foreach和acc不起作用。 acc不知道我在该方法中设置的名称,说明和ID。我至少接近对吗?

+0

不,同一个项目,但我想将它们分成不同的项目。所以,假设他们现在是分开的。 – Craig 2011-01-08 05:54:39

+0

你的服务是在远程?最好使用`var`代替这个参数类型。 – 2011-01-08 05:55:48

+0

我想知道是否应该建立一个共享类lib,它具有'传输对象'。所以在我的方法中,我获取数据,并将它们加载到List 中,然后返回该数据。那么执行linq的项目和GUI都会知道类型? – Craig 2011-01-08 05:55:58

回答

4

@BrokenGlass是正确的,问题的根源在于你使用匿名类型。这会导致您使用IEnumerable的非泛型版本,该版本不知道对象是什么类型。

虽然(它需要.NET 4.0对你来说可能不是问题),但我会建议创建一个实际的Account类,而不是使用dynamic

这样你可以返回一个IEnumerable<Account>而不是仅仅IEnumerable。然后你就可以使用这些属性,因为它知道它是一个账户。

一旦创建了Account类的方法就变成了:

public static IEnumerable<Account> GetDetailedAccounts() 
{ 
    IEnumerable<Account> accounts = (from a in Db.accounts 
        join i in Db.financial_institution on a.financial_institution.financial_institution_id 
         equals i.financial_institution_id 
        join acct in Db.z_account_type on a.z_account_type.account_type_id equals 
         acct.account_type_id 
        orderby i.name 
        select new Account {account_id = a.account_id, name = i.name, description = acct.description}); 
    return accounts; 

} 

然后调用代码可以保持不变。

我想我应该指出,var不按照您认为它的方式工作。变量的类型仍然是编译时确定的,这意味着(大部分)它只是一个快捷方式。您的示例将与您使用object而不是var相同,因为IEnumerable只能包含object

如果你在.NET工作,我建议遵循.NET命名约定,尽管如此AccountId而不是account_id,但这不会影响它是否有效。

1

问题是您正在使用该方法的用户没有办法转回的匿名类型。出(除了反射或创建一个类)一个简单的方法是使用dynamic,因为你知道你想打开的属性有:

例子:(十分由我承认)

public static IEnumerable GetAccounts() 
{ 
    return Enumerable.Range(0, 10) 
      .Select(x => new { Id = x, Name = "herbert" }); 
} 

//... 
foreach (dynamic account in GetAccounts()) 
{ 
    Console.WriteLine(string.Format("Id: {0}, Name: {1}", 
         account.Id, 
         account.Name)); 
} 

返回到您的代码,这将意味着只是改变了调用代码:

foreach (dynamic acc in accounts) 
{ 
    Console.WriteLine(string.Format("{0:00} {1}", acc.account_id, acc.name + " " + acc.description)); 
} 
0

Davy8是正确的,也创建自定义的BusinessObject的(AccountDetail)将是长期的外部库的生命周期更好的解决方案(如果你在你的逻辑/代码使用该AccountDetail很多),因为你可以自定义它只要你想
具有传递类(AccountDetail)轻轻松松让你绑定回在设计时的一些UI,使你的项目的概念,更有点清楚,还可以更经常地重新使用它

public class AccountDetail 
{ 
public string AccountID{get;set;} 
public string AccountName {get;set;} 
public string AccountDescription {get;set} 

public AccountDetail(){} 
} 

so查询为:

public static List<AccountDetail> GetDetailedAccounts() 
{ 
    return (from a in Db.accounts 
     join i in Db.financial_institution on a.financial_institution.financial_institution_id 
equals i.financial_institution_id 
join acct in Db.z_account_type on a.z_account_type.account_type_id equals 
acct.account_type_id 
orderby i.name 
select new AccountDetail 
{ AccountID = a.account_id, 
    AccountName= i.name, 
     AccountDescription= acct.description} 

}).ToList();