好的,我正在使用2层类:某个“经理”类,其任务是获取一个对象,链接所有附加到它的项目,然后将其返回给调用者,以及一个“数据”类。任务是根据特定请求调用数据库。
这是我工作方式的一个例子。这是一个“经理”课程:
public class CardManager
{
private static readonly CardData mCardDAL = new CardData();
public List<CardDisplay> ListCardsToShow(int _pageNumber, string _queryString, string _rarity, string _type, string _color, out int _totalCount)
{
List<CardDisplay> listToReturn = mCardDAL.ListCardsToShow(_pageNumber, _queryString, _rarity, _type, _color, out _totalCount);
LinkListCardDisplayData(listToReturn);
return listToReturn;
}
/// <summary>
/// Method links the card set with each cards of the list.
/// </summary>
/// <param name="_listToReturn"></param>
private static void LinkListCardDisplayData(IEnumerable<CardDisplay> _listToReturn)
{
try
{
foreach (CardDisplay item in _listToReturn)
{
LinkCardDisplayData(item);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
private static void LinkCardDisplayData(CardDisplay _item)
{
_item.mMasterCardID = _item.mMasterCard.mCardID;
ImagesManager.GetCardImages(_item);
if (_item.mChildCard != null)
{
_item.mChildCardID = _item.mChildCard.mCardID;
}
}
}
这是一个“数据”类,即此事件中的CardData
类:
public class CardData
{
internal List<CardDisplay> ListCardsToShow(int _pageNumber, string _queryString, string _rarity, string _type, string _color, out int _totalCount)
{
using (DatabaseEntity db = new DatabaseEntity())
{
db.Database.Connection.Open();
List<CARD> cardData;
List<CardInfo> listCards;
if (!String.IsNullOrWhiteSpace(_queryString))
{
var predicate = GetCardPredicate(_queryString);
if (_rarity != "All")
{
predicate = predicate.And(_item => _item.CARD_RARTY == _rarity);
}
if (_color != "All")
{
predicate = predicate.And(
_item => _item.CARD_MANA_COST.Contains(_color) || _item.CARD_COLOR.Contains(_color));
}
if (_type != "All")
{
predicate = predicate.And(_item => _item.CARD_TYPE.Contains(_type));
}
var cardQry = from c in db.CARD.AsExpandable().Where(predicate)
select c;
_totalCount = cardQry.Count();
int pageCount = _pageNumber - 1;
cardData = cardQry.OrderBy(_x => _x.CARD_IDE).Skip(pageCount * 20).Take(20).ToList();
for (int i = 0; i < cardData.Count; i++)
{
CARD card = cardData[i];
if (cardData.Any(_item => _item.CARD_MASTER_IDE == card.CARD_IDE))
{
cardData.Remove(card);
}
}
listCards = DataConverter.ListCardDATAToListCardInfo(cardData);
}
else
{
// If we are here then the user browsed to get the 300 latest entries available.
Expression<Func<CARD, bool>> cardPredicate = PredicateBuilder.True<CARD>();
if (_rarity != "All")
{
cardPredicate = cardPredicate.And(_item => _item.CARD_RARTY == _rarity);
}
if (_type != "All")
{
cardPredicate = cardPredicate.And(_item => _item.CARD_TYPE.Contains(_type));
}
if (_color != "All")
{
cardPredicate =
cardPredicate.And(
_item => _item.CARD_MANA_COST.Contains(_color) || _item.CARD_COLOR.Contains(_color));
}
var cardQry = (from c in db.CARD.AsExpandable().Where(_item => !_item.CARD_NAME.Contains("(Foil)"))
select c).OrderByDescending(_x => _x.CARD_SET.CARD_SET_RELES_DATE).Take(300);
cardQry = cardQry.Where(cardPredicate);
_totalCount = cardQry.Count();
int pageCount = _pageNumber - 1;
cardData = cardQry.Skip(pageCount * 20).Take(20).ToList();
for (int i = 0; i < cardData.Count; i++)
{
CARD card = cardData[i];
if (cardData.Any(_item => _item.CARD_MASTER_IDE == card.CARD_IDE))
{
cardData.Remove(card);
}
}
listCards = DataConverter.ListCardDATAToListCardInfo(cardData);
}
List<CardDisplay> listToReturn = MakeListCardDisplay(listCards);
return listToReturn;
}
}
}
我的问题不是关于“我如何”执行我的代码(但我可以自由地做出建设性的评论,因为我喜欢学习),而是关于它是如何构建的。我想,例如,一个CardData
类完全由public static readonly CardData mCardDAL = new CardData();
对象在控制器中。
有没有办法隔离我的课程,以至于任何人都被“强迫”通过经理来获取对象?我工作得很好,我的代码好吗?
答案 0 :(得分:4)
可以通过在CardData
中设置Manager
嵌套类来拒绝来自外部的访问,通过使其成为protected
来阻止它的构造函数,并创建一个private
实例类:
public class Manager
{
public class Manager
{
CardData c = new CardDataInternal();
}
private class CardDataInternal : CardData
{
public CardDataInternal()
{ }
}
public class CardData
{
protected CardData()
{ }
}
}
答案 1 :(得分:3)
您可以通过将 manager 类设置为嵌套类来保持两个对象公开,然后为Card
类提供私有构造函数(允许嵌套类调用),类似于:
public class Card
{
private Card()
{
}
public class Manager
{
public Card Create()
{
return new Card();
}
}
}
因此,您可以自由创建new Card.Manager()
,但创建新Card
的唯一方法是使用Create()
方法。
答案 2 :(得分:2)
使用接口的@ Patrick方法的替代方法:
public interface ICardData { ... }
public class Manager
{
public class Manager()
{
CardData c = new CardData();
}
private class CardData : ICardData
{
public CardData() { }
}
}
通过在嵌套的私有类上使用接口而不是构造函数,您还可以设置使用模拟实现进行单元测试...对于CardData可能不重要但是如果您在具有此类的类上执行此操作有趣的行为,非常重要。
答案 3 :(得分:1)
从提供的代码中,您可能希望将CardData类放在CardManager类中并将其设置为私有,以便只有CardManager才能访问它。
public class CardManager
{
private class CardData { ... }
}