C# 如何使功能更强大?
我是一个c#人,最近学习了JavaScript,并考虑走f#路。我喜欢JavaScript的功能性,但很难将其应用到我的c代码中。我看了下面的代码块,感觉真的很难看。对于那些天生热衷于函数式编程的人来说,用c(甚至f)来完成这一块的更好方法是什么 (或者我是不是找错了地方想改进它)C# 如何使功能更强大?,c#,f#,C#,F#,我是一个c#人,最近学习了JavaScript,并考虑走f#路。我喜欢JavaScript的功能性,但很难将其应用到我的c代码中。我看了下面的代码块,感觉真的很难看。对于那些天生热衷于函数式编程的人来说,用c(甚至f)来完成这一块的更好方法是什么 (或者我是不是找错了地方想改进它) // ///根据tenantNameOverride获取当前租户(如果存在), ///否则,使用urlHost来解决这个问题 ///独立案例 ///如果urlHost和tenantNameOverride为空,则 /
//
///根据tenantNameOverride获取当前租户(如果存在),
///否则,使用urlHost来解决这个问题
///独立案例
///如果urlHost和tenantNameOverride为空,则
///抛出异常
///如果指定了tenantNameOverride但未找到
///抛出异常
///如果未指定tenantNameOverride,则
///没有默认租户,则引发异常
///
///
///
///
///
私有静态租户GetTenantBasedOnUrlHost(
列出租户,字符串urlHost=null,
字符串tenantNameOverride=null)
{
if(String.IsNullOrEmpty(urlHost)&&
String.IsNullOrEmpty(租户名称覆盖))
{
抛出新的ApplicationException(
“必须指定URL主机或租户名称”);
}
租户;
if(String.IsNullOrEmpty(tenantNameOverride))
{
租户=租户。
FirstOrDefault(a=>a.DomainName.ToLower().Equals(urlHost))??
tenants.FirstOrDefault(a=>a.Default);
if(租户==null)
{
抛出新的ApplicationException
(“必须指定租户名称,未找到默认租户”);
}
}
其他的
{
租户=租户。第一个或默认值
(a=>a.Name.ToLower()==tenantNameOverride.ToLower());
if(租户==null)
{
抛出新的ApplicationException
(“指定了租户名称,但未找到”);
}
}
归还承租人;
}
/*********************更新如下*****************/
根据Jon Skeet的建议,我提出了两种方法。除了顶部的空字符串冲突错误检查之外,我不确定我们在c#中是否可以轻松避免。抛出一个异常在NotFound上也感觉有点奇怪,但是出于我的目的,这些方法应该总是找到一个租户,如果不是的话,这是意外的,异常似乎是合理的
这看起来更干净,更符合单一责任的设计准则。也许这就是我不喜欢我的解决方案的原因,它与功能性或非功能性无关
/// <summary>
/// Return tenant based on URL (or return default tenant if exists)
/// </summary>
/// <param name="tenants"></param>
/// <param name="urlHost"></param>
/// <returns></returns>
private static Tenant GetTenantBasedOnUrl(
List<Tenant> tenants, string urlHost)
{
if (String.IsNullOrEmpty(urlHost))
{
throw new ApplicationException(
"urlHost must be specified");
}
var tenant = tenants.
FirstOrDefault(a => a.DomainName.ToLower().Equals(urlHost)) ??
tenants.FirstOrDefault(a => a.Default);
if (tenant == null)
{
throw new ApplicationException
("tenant not found based on URL, no default found");
}
return tenant;
}
/// <summary>
/// Get exact tenant name match and do not return default even
/// if exists.
/// </summary>
/// <param name="tenants"></param>
/// <param name="tenantNameOverride"></param>
/// <returns></returns>
private static Tenant GetTenantByName(List<Tenant> tenants,
string tenantNameOverride)
{
if (String.IsNullOrEmpty(tenantNameOverride))
{
throw new ApplicationException(
"tenantNameOverride or tenantName must be specified");
}
var tenant = tenants.FirstOrDefault
(a => a.Name.ToLower() == tenantNameOverride.ToLower());
if (tenant == null)
{
throw new ApplicationException
("No tenant Found (not checking for default)");
}
return tenant;
}
}
//
///基于URL返回租户(如果存在,则返回默认租户)
///
///
///
///
私有静态租户GetTenantBasedOnUrl(
列出租户,字符串URL(主机)
{
if(String.IsNullOrEmpty(urlHost))
{
抛出新的ApplicationException(
“必须指定URL主机”);
}
var tenant=租户。
FirstOrDefault(a=>a.DomainName.ToLower().Equals(urlHost))??
tenants.FirstOrDefault(a=>a.Default);
if(租户==null)
{
抛出新的ApplicationException
(“根据URL未找到租户,未找到默认值”);
}
归还承租人;
}
///
///获取精确的租户名称匹配,并且不返回默认值
///如果存在。
///
///
///
///
私有静态租户GetTenantByName(列出租户,
字符串tenantNameOverride)
{
if(String.IsNullOrEmpty(tenantNameOverride))
{
抛出新的ApplicationException(
“必须指定tenantNameOverride或tenantName”);
}
var tenant=tenants.FirstOrDefault
(a=>a.Name.ToLower()==tenantNameOverride.ToLower());
if(租户==null)
{
抛出新的ApplicationException
(“未找到租户(未检查默认值)”;
}
归还承租人;
}
}
以下是我如何处理F#中的问题
首先,如果我正确理解了需求,那么函数的调用方必须提供域名或租户名称来搜索。在C#中,这种排他规则很难建模,这导致至少必须指定一个规则,但如果两个都指定了,则其中一个参数优先
虽然使用C#的类型系统很难定义这样的规则,但在F#中使用一个有区别的并集来声明是很简单的:
类型租户标准=
|Uri的域名
|字符串名称
这意味着搜索租户的条件可以是DomainName
或名称,但决不能同时是两者
在我对DomainName
的定义中,我将类型更改为System.Uri
。在处理URL时,通常使用Uri
值比string
值更安全
与其将string
值转换为小写,不如使用StringComparison.OrdinalIgnoreCase
比较它们,如果您需要的话,因为如果您将土耳其字符串转换为小写,会出现各种微妙的本地化问题(这种转换是有损的)
最后,我将查询更改为返回租户选项
,而不是抛出异常。在函数式编程中,我们更喜欢避免异常。如果您想要比选项
更详细的异常处理,您可以
综上所述,下面是查找租户功能的一个可能实现:
让findTenant租户=函数
|域名u->
让t=tenants |>List.tryFind(乐趣x->x.DomainName=u)
匹配
|一些t->一些t
|无->租户>
/// <summary>
/// Return tenant based on URL (or return default tenant if exists)
/// </summary>
/// <param name="tenants"></param>
/// <param name="urlHost"></param>
/// <returns></returns>
private static Tenant GetTenantBasedOnUrl(
List<Tenant> tenants, string urlHost)
{
if (String.IsNullOrEmpty(urlHost))
{
throw new ApplicationException(
"urlHost must be specified");
}
var tenant = tenants.
FirstOrDefault(a => a.DomainName.ToLower().Equals(urlHost)) ??
tenants.FirstOrDefault(a => a.Default);
if (tenant == null)
{
throw new ApplicationException
("tenant not found based on URL, no default found");
}
return tenant;
}
/// <summary>
/// Get exact tenant name match and do not return default even
/// if exists.
/// </summary>
/// <param name="tenants"></param>
/// <param name="tenantNameOverride"></param>
/// <returns></returns>
private static Tenant GetTenantByName(List<Tenant> tenants,
string tenantNameOverride)
{
if (String.IsNullOrEmpty(tenantNameOverride))
{
throw new ApplicationException(
"tenantNameOverride or tenantName must be specified");
}
var tenant = tenants.FirstOrDefault
(a => a.Name.ToLower() == tenantNameOverride.ToLower());
if (tenant == null)
{
throw new ApplicationException
("No tenant Found (not checking for default)");
}
return tenant;
}
}