hhjkk

要将流水号生成逻辑实现为一个 C# 特性(Attribute),你可以通过自定义属性来实现。自定义属性通常用于元数据标注,但在这种情况下,你可以创建一个特性来生成并管理流水号。

以下是一个示例,展示如何创建一个自定义特性来生成流水号:

### 1. 创建自定义特性

首先,创建一个自定义特性类 `SerialNumberAttribute`:

```csharp
using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class SerialNumberAttribute : Attribute
{
    private static readonly object _lock = new object();
    private static int _currentNumber = 0;
    private static DateTime _lastGeneratedDate = DateTime.MinValue;

    public string SerialNumber { get; private set; }

    public SerialNumberAttribute()
    {
        lock (_lock)
        {
            var currentDate = DateTime.Now;
            if (_lastGeneratedDate.Year != currentDate.Year || _lastGeneratedDate.Month != currentDate.Month)
            {
                _currentNumber = 1;
                _lastGeneratedDate = currentDate;
            }
            else
            {
                _currentNumber++;
            }

            SerialNumber = $"F{currentDate:yyMM}{_currentNumber:0000}";
        }
    }
}
```

### 2. 使用自定义特性

你可以在类或方法上使用这个自定义特性:

```csharp
[SerialNumber]
public class MyClass
{
    public void PrintSerialNumber()
    {
        var serialNumberAttribute = (SerialNumberAttribute)Attribute.GetCustomAttribute(typeof(MyClass), typeof(SerialNumberAttribute));
        Console.WriteLine($"Generated Serial Number: {serialNumberAttribute.SerialNumber}");
    }
}
```

### 3. 示例用法

以下是一个示例展示如何使用和测试这个自定义特性:

```csharp
class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        myClass.PrintSerialNumber();

        // Simulate creation of another instance in the same month
        var anotherClass = new MyClass();
        anotherClass.PrintSerialNumber();

        // Simulate creation of another instance in the next month
        System.Threading.Thread.Sleep(1000); // Sleep for a second to simulate time passing
        var nextMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month + 1, 1);
        SystemClock.SetDateTime(nextMonth); // Assuming you have a way to mock the system clock
        var nextMonthClass = new MyClass();
        nextMonthClass.PrintSerialNumber();
    }
}
```

### 注意事项

1. **线程安全**:在特性中使用了 `lock` 关键字来确保线程安全。
2. **日期重置**:每当月份变化时,流水号会从 `0001` 开始重新计数。
3. **持久化**:如果需要跨应用程序运行持久化流水号(例如,重启后仍然保持计数),你需要将计数存储在数据库或文件中,而不是仅在内存中。

### 持久化实现

如果需要持久化流水号,可以将计数存储到数据库中,以下是一个示例:

```csharp
public sealed class SerialNumberAttribute : Attribute
{
    private static readonly object _lock = new object();
    private static ApplicationDbContext _context;

    public string SerialNumber { get; private set; }

    public SerialNumberAttribute()
    {
        _context = new ApplicationDbContext(); // 假设你有一个无参构造函数
        lock (_lock)
        {
            var currentDate = DateTime.Now;
            var year = currentDate.Year;
            var month = currentDate.Month;

            var serialNumber = _context.SerialNumbers
                .FirstOrDefault(sn => sn.Year == year && sn.Month == month);

            if (serialNumber == null)
            {
                serialNumber = new SerialNumber
                {
                    Year = year,
                    Month = month,
                    CurrentNumber = 1
                };
                _context.SerialNumbers.Add(serialNumber);
            }
            else
            {
                serialNumber.CurrentNumber++;
            }

            _context.SaveChanges();

            SerialNumber = $"F{year % 100:00}{month:00}{serialNumber.CurrentNumber:0000}";
        }
    }
}
```

通过以上方法,你可以创建一个自定义特性来生成流水号,并且可以根据需要将流水号持久化到数据库中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值